Moje pytanie jako tytuł powyżej. Na przykład,
IEnumerable<T> items = new T[]{new T("msg")};
items.ToList().Add(new T("msg2"));
ale w końcu ma tylko 1 przedmiot.
Czy możemy mieć taką metodę items.Add(item)
?
podobnie jak List<T>
c#
list
ienumerable
ldsenow
źródło
źródło
IEnumerable<T>
jest przeznaczony tylko do wysyłania zapytań do kolekcji. Jest to szkielet szkieletu LINQ. Zawsze jest abstrakcją z innej kolekcji, takich jakCollection<T>
,List<T>
lubArray
. Interfejs udostępnia tylkoGetEnumerator
metodę zwracającą instancję,IEnumerator<T>
która umożliwia przechodzenie rozszerzonej kolekcji po jednym elemencie na raz. Interfejs rozszerzeń LINQ jest ograniczony przez ten interfejs.IEnumerable<T>
jest przeznaczony tylko do odczytu, ponieważ może reprezentować agregację części wielu kolekcji.IList<T>
zamiastIEnumerable<T>
:IList<T> items = new T[]{new T("msg")}; items.Add(new T("msg2"));
Odpowiedzi:
Nie możesz, ponieważ
IEnumerable<T>
niekoniecznie oznacza kolekcję, do której można dodać elementy. W rzeczywistości niekoniecznie reprezentuje kolekcję! Na przykład:Możesz jednak utworzyć nowy
IEnumerable
obiekt (nieokreślonego typu), który po wyliczeniu dostarczy wszystkie elementy starego oraz niektóre własne. UżywaszEnumerable.Concat
do tego:To nie zmieni obiektu Array (nie można wstawiać elementy do do tablic, tak). Ale stworzy nowy obiekt, który wyświetli listę wszystkich elementów w tablicy, a następnie „Foo”. Ponadto ten nowy obiekt będzie śledził zmiany w tablicy (tzn. Ilekroć go wyliczysz, zobaczysz bieżące wartości elementów).
źródło
Concat
jest wywoływana wielokrotnie; a jeśli tak, to i tak masz większe problemy, ponieważ za każdym razemConcat
dostajesz jeszcze jedną warstwę modułu wyliczającego - więc na końcu pojedyncze wywołanieMoveNext
spowoduje łańcuch połączeń równy długości iteracji.IEnumerable<T>
w języku C #, w tym przeładowanie,operator+
ponieważConcat
(nawiasem mówiąc, czy wiesz, że w VB możesz indeksować,IEnumerable
jakby to była tablica - używaElementAt
pod maską): connect.microsoft.com / VisualStudio / feedback /… . Jeśli otrzymamy jeszcze dwa przeciążenia,Concat
aby wziąć pojedynczy przedmiot zarówno po lewej, jak i po prawej stronie, zmniejszy to pisanie doxs +=x
- więc idź poke Mads (Torgersen), aby nadać temu priorytetowi w C # 5.0 :)Typ
IEnumerable<T>
nie obsługuje takich operacji. CelemIEnumerable<T>
interfejsu jest umożliwienie konsumentowi zobaczyć zawartość kolekcji. Nie modyfikować wartości.Wykonując operacje takie jak .ToList (). Add (), tworzysz nowy
List<T>
i dodajesz wartość do tej listy. Nie ma połączenia z oryginalną listą.Możesz użyć metody Dodaj rozszerzenie, aby utworzyć nową
IEnumerable<T>
z wartością dodaną.Nawet w tym przypadku nie zmodyfikuje oryginalnego
IEnumerable<T>
obiektu. Można to zweryfikować, trzymając odniesienie do niego. Na przykładPo tym zestawie operacji zmienna temp będzie nadal odwoływała się do wyliczenia z pojedynczym elementem „foo” w zbiorze wartości, podczas gdy pozycje będą odwoływać się do innego wyliczenia z wartościami „foo” i „bar”.
EDYTOWAĆ
Ciągle zapominam, że Add nie jest typową metodą rozszerzenia,
IEnumerable<T>
ponieważ jest to jedna z pierwszych metod, które ostatecznie definiuję. Oto jestźródło
Concat
:)Add
jednak, ponieważAdd
praktycznie na każdym innym typie .NET (nie tylko kolekcje) mutuje kolekcję w miejscu. MożeWith
? Może to być nawet kolejne przeciążenieConcat
.Concat
że przeciążenie byłoby prawdopodobnie lepszym wyborem, ponieważAdd
zwykle implikuje zmienność.return e.Concat(Enumerable.Repeat(value,1));
?Czy zastanawiałeś się nad użyciem
ICollection<T>
lubIList<T>
interfejsów, istnieją one z tego samego powodu, dla którego chcesz miećAdd
metodę naIEnumerable<T>
.IEnumerable<T>
służy do „oznaczania” typu jako… cóż, policzalnego lub tylko sekwencji elementów bez konieczności zapewnienia jakiejkolwiek gwarancji, czy prawdziwy obiekt leżący u podstaw obsługuje dodawanie / usuwanie elementów. Pamiętaj również, że te interfejsy są implementowane,IEnumerable<T>
dzięki czemu otrzymujesz również wszystkie metody rozszerzeńIEnumerable<T>
.źródło
Kilka krótkich, słodkich metod przedłużania
IEnumerable
iIEnumerable<T>
zrób to dla mnie:Elegancki (cóż, z wyjątkiem nietypowych wersji). Szkoda, że tych metod nie ma w BCL.
źródło
ToString()
na nim, ponieważ to przechwytuje więcej szczegółów błędów. Sądzę, że nie znalazłeś sięinclude System.Linq;
na początku pliku, ale kto wie? Spróbuj samemu to ustalić, stwórz minimalny prototyp, który pokazuje ten sam błąd, jeśli nie możesz, a następnie poproś o pomoc w pytaniu.W .net Core istnieje metoda
Enumerable.Append
, która właśnie to robi.Kod źródłowy metody jest dostępny na GitHub. .... Wdrożenie (bardziej wyrafinowane niż sugestie z innych odpowiedzi) jest warte obejrzenia :).
źródło
Nie IEnumerable nie obsługuje dodawania do niego elementów.
„Alternatywą” jest:
źródło
Aby dodać drugą wiadomość, musisz:
źródło
Nie tylko nie możesz dodawać elementów w taki sposób, jak podajesz, ale jeśli dodasz element do
List<T>
(lub prawie każdej innej kolekcji nie tylko do odczytu), dla której masz istniejący moduł wyliczający, moduł wyliczający jest unieważniany (InvalidOperationException
od tego momentu wyrzuca ).Jeśli agregujesz wyniki z pewnego rodzaju zapytania o dane, możesz użyć
Concat
metody rozszerzenia:Edycja: pierwotnie użyłem
Union
rozszerzenia w tym przykładzie, co nie jest tak naprawdę poprawne. Moja aplikacja korzysta z niego w szerokim zakresie, aby nakładające się zapytania nie dublowały wyników.źródło
Przyszedłem tutaj, aby powiedzieć, że oprócz
Enumerable.Concat
metody rozszerzenia, wydaje się, że istnieje inna metoda o nazwieEnumerable.Append
w .NET Core 1.1.1. Ta ostatnia pozwala połączyć jeden element z istniejącą sekwencją. Tak więc odpowiedź Aamola można również zapisać jakoPamiętaj jednak, że ta funkcja nie zmieni sekwencji wejściowej, po prostu zwróci opakowanie, które połączy daną sekwencję i dołączony element.
źródło
Inni podali już świetne wyjaśnienia dotyczące tego, dlaczego nie możesz (i nie powinieneś!) Mieć możliwości dodawania elementów do
IEnumerable
. Dodam tylko, że jeśli chcesz kontynuować kodowanie do interfejsu reprezentującego kolekcję i chcesz dodać metodę, powinieneś kodować doICollection
lubIList
. Jako dodatkowa bonanza implementują te interfejsyIEnumerable
.źródło
możesz to zrobić.
źródło
Najłatwiejszym sposobem na to jest po prostu
Następnie możesz zwrócić listę jako IEnumerable, ponieważ implementuje interfejs IEnumerable
źródło
Jeśli utworzysz obiekt tak, jak
IEnumerable<int> Ones = new List<int>();
możesz, możesz to zrobić((List<int>)Ones).Add(1);
źródło
Jasne, że możesz (odkładam na bok swój biznes T):
źródło