Mam numer IEnumerable<T>
i potrzebuję jego kopii. Wszystko, co implementuje IEnumerable<T>
, będzie dobrze. Jaki jest najtańszy sposób na skopiowanie? .ToArray()
może?Najtańszy sposób na skopiowanie IEnumerable <T>?
Odpowiedz
ToArray
niekoniecznie jest szybszy niż ToList
. Po prostu użyj ToList
.
Punkt jest tak długi, jak długo nie znasz liczby elementów oryginalnej sekwencji przed wyliczeniem, kończy się zmiana rozmiaru tablicy i dodawanie do niej elementów takich jak List<T>
, więc ToArray
będzie musiał wykonać to samo robi List<T>
. Poza tym ToList
daje ci List<T>
i jest ładniejszy niż surowa tablica.
Oczywiście, jeśli znasz konkretny typ instancji IEnumerable<T>
, mogą istnieć szybsze metody, ale nie jest to istotne.
Nota boczna: użycie tablicy (chyba że musisz) jest prawdopodobnie mikro-optymalizacją i powinno być avoidedmost of the time.
Drugim najtańszym sposobem jest podanie new List<T>(myEnumerable).ToArray()
. Najtańszym sposobem jest użycie albo .ToArray()
(z LINQ) lub, jeśli nie masz C# 3.5, aby utworzyć własny bufor i dodać do niego, podwajając jego rozmiar, a następnie przyciąć go na końcu.
Enumerable::ToArray
i Enumerable::ToList
ostatecznie użyciu tej samej techniki, aby otrzymać elementy od źródła do bufora tablicy wewnętrznego, a po osiągnięciu wielkości tego buforu będą przydziela nowy bufor dwukrotnie większy, memcpy się i dalej dodawać elementy, powtarzając ten proces, aż zakończy się wyliczanie źródła. Różnica na końcu polega na tym, że ToArray
, która wewnętrznie korzysta z implementacji Buffer<T>
, musi następnie przydzielić dokładnie rozmiar Array
i skopiować elementy do niej przed zwróceniem wyniku. Z drugiej strony, ToList
po prostu musi zwrócić List<T>
z potencjalnie (prawdopodobnie) tylko częściowo wypełnionym buforem tablicowym wewnątrz niego.
Obie implementacje mają również optymalizację gdzie jeśli źródłem IEnumerable
jest ICollection
będą one rzeczywiście przeznaczyć dokładnie odpowiedni rozmiar bufora, aby rozpocząć z użyciem ICollection::Count
a następnie użyć ICollection::CopyTo
od źródła do wypełnienia swoich buforów.
Na koniec okaże się, że zachowują się prawie identycznie w większości sytuacji, ale List<T>
jest technicznie "cięższą" klasą, do której można się przyczepić, a ToArray
ma dodatkowy przydział + memcpy na końcu (jeśli źródłem nie jest ICollection
), aby móc przekazać dokładnie odpowiednią wielkość tablicy. Zwykle trzymam się z ToList
, chyba że wiem, że muszę przekazać wynik do czegoś, co wymaga tablicy, powiedzmy może Task::WaitAll
.
Chciałem zasugerować możliwość użycia , jeśli masz do dyspozycji TPL, ale nieformalne testy na moim dwurdzeniowym laptopie pokazują, że jest on 7 razy wolniejszy niż tylko .ToList()
. Więc trzymaj się z Mehrdad'sanswer.
+1 Jest to potencjalnie dobra alternatywa, a w zależności od charakteru obiektu odbiorcy może być znacznie szybsza, ale ta kategoria jest "nieistotna do punktu". –
Wiem, że to dość stary ...
Dlaczego nie można zrobić coś takiego ...
IEnumerable <T> original = {... wstaw tutaj kod do wypełnienia ...};
IEnumerable <T> copy = (z rzędu w oryginalnym wybranym wierszu);
Użyłem tej metody wcześniej, aby odłożyć ładowanie kopii i jej elementów, dopóki ich nie potrzebuję, oraz, że nie zmienię podstawowego typu danych na "oryginalny", przesyłając go do typu listy.
Wybór tożsamości tak naprawdę nie daje niczego tutaj. Nie jest to tak naprawdę funkcjonalnie odmienne od kopiowania odniesienia do innego "IEnumerable", inne niż to, że dodaje trochę dodatkowych kosztów w czasie wykonywania i zapobiega rzutowaniu na ukryty typ. Jeśli chcesz uzyskać migawkę tego, jak wygląda sekwencja w danym momencie, właściwym rozwiązaniem jest 'ToList'. Jeśli nie, a chcesz sekwencji, która jest generowana w tym samym dworze, co druga sekwencja, po prostu skopiuj referencję; nie trzeba robić nic więcej. – Servy
- 1. Jaki jest najlepszy sposób na skopiowanie listy?
- 2. Spłaszczyć IEnumerable <IEnumerable <>>; zrozumienia rodzajowych
- 3. Licz na IEnumerable <dynamic>
- 4. IEnumerable <IEnumerable <T>> do IEnumerable <T> użyciu LINQ
- 5. Konwertuj DataTable na IEnumerable <T>
- 6. Konwertuj IEnumerable <int> na int []
- 7. Konwertuj na IEnumerable <dynamic>?
- 8. Przesyłaj/przeliczaj IEnumerable <T> na IEnumerable <U>?
- 9. IEnumerable <> to IList <>
- 10. Dlaczego IEnumerable <T> jest zdefiniowany jako IEnumerable <out T>, nie IEnumerable <T>
- 11. Jaki jest najlepszy sposób na skopiowanie bazy danych?
- 12. Czy istnieje prosty sposób na skopiowanie treści TDictionary do innej?
- 13. Łatwy sposób na skopiowanie starych wtyczek do nowej instalacji Eclipse
- 14. Najlepszy sposób na skopiowanie wektora do listy w STL?
- 15. Szybszy sposób na skopiowanie bazy danych PostgreSQL (lub najlepszego sposobu)
- 16. Różnica między IEnumerable i IEnumerable <T>?
- 17. Jak sprawdzić, czy `IEnumerable <T1>` covariant do `IEnumerable <T2>`?
- 18. Casting IEnumerable <T> do listy <T>
- 19. NET Reflection: Wykrywanie IEnumerable <T>
- 20. Jak czekać na całkowite skopiowanie pliku?
- 21. XML do IEnumerable <T>
- 22. C# Nie można przekonwertować z IEnumerable <Base> do IEnumerable <Derived>
- 23. Dlaczego funkcja, która trwa IEnumerable <interface>, nie przyjmuje IEnumerable <class>?
- 24. Nie można przekonwertować listy <KeyValuePair <...,...>> na IEnumerable <object>?
- 25. Zdefiniuj metodę rozszerzenia dla IEnumerable <T>, która zwraca IEnumerable <T>?
- 26. Przesyłanie z IEnumerable <Object> do IEnumerable <string>
- 27. Jak połączyć dwa IEnumerable <T> w nowy IEnumerable <T>?
- 28. Jak przekonwertować IEnumerable <T> na ciąg, rekursywnie?
- 29. Jak zrobić IEnumerable <T> readonly?
- 30. F # odpowiednik C# typeof (IEnumerable <>)
Uwaga: są one praktycznie równoważne. – Vadim
@Yads: dokładnie. –
+1. W rzeczywistości Mono ['Enumerable.ToArray'] (https://github.com/mono/mono/blob/master/mcs/class/System.Core/System.Linq/Enumerable.cs#L2794) używa' nowej listy (źródło) .ToArray() ', chyba że' IEnumerable 'dzieje się jako' ICollection '. Nie byłbym zaskoczony, gdyby stwardnienie rozsiane było podobne. –