Jak Mogę dodać przedmiot do kolekcji IEnumerable?
Moje pytanie jak tytuł wyż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 w środku.
Czy możemy mieć metodę taką jak items.Add(item)
?
Jak List<T>
13 answers
Nie możesz, ponieważ IEnumerable<T>
niekoniecznie reprezentuje kolekcję, do której można dodawać elementy. W rzeczywistości wcale nie musi reprezentować kolekcji! Na przykład:
IEnumerable<string> ReadLines()
{
string s;
do
{
s = Console.ReadLine();
yield return s;
} while (s != "");
}
IEnumerable<string> lines = ReadLines();
lines.Add("foo") // so what is this supposed to do??
Możesz jednak stworzyć Nowy IEnumerable
obiekt (nieokreślonego typu), który po wyliczeniu dostarczy wszystkie elementy starego, plus niektóre własne. Używasz Enumerable.Concat
do tego:
items = items.Concat(new[] { "foo" });
To nie zmieni obiektu array (nie można wstawiać elementów do tablice, zresztą). Ale utworzy nowy obiekt, który wyświetli wszystkie elementy w tablicy, a następnie "Foo". Co więcej, ten nowy obiekt będzie śledził zmiany w tablicy (tzn. gdy ją wyliczysz, zobaczysz bieżące wartości pozycji).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-12 21:04:06
Typ IEnumerable<T>
nie obsługuje takich operacji. Celem interfejsu IEnumerable<T>
jest umożliwienie konsumentowi przeglądania zawartości kolekcji. Nie modyfikować wartości.
Kiedy robisz operacje jak .ToList().Add() tworzysz nową List<T>
i dodajesz wartość do tej listy. Nie ma połączenia z oryginalną listą.
Możesz użyć metody Add extension, aby utworzyć nową IEnumerable<T>
z wartością dodaną.
items = items.Add("msg2");
Nawet w tym przypadku nie będzie zmodyfikuj oryginalny obiekt IEnumerable<T>
. Można to sprawdzić, trzymając odniesienie do niego. Na przykład
var items = new string[]{"foo"};
var temp = items;
items = items.Add("bar");
Po Tym Zestawie operacji zmienna temp nadal będzie odwoływać się tylko do wyliczenia z pojedynczym elementem " foo "w zestawie wartości, podczas gdy pozycje będą odwoływać się do innego wyliczenia z wartościami" foo "i"bar".
EDIT
Zapominam, że Add nie jest typową metodą rozszerzenia na IEnumerable<T>
, ponieważ jest jedną z pierwszych, które kończę definiowanie. Tutaj jest
public static IEnumerable<T> Add<T>(this IEnumerable<T> e, T value) {
foreach ( var cur in e) {
yield return cur;
}
yield return value;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-31 02:05:56
Czy rozważałeś użycie ICollection
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-27 16:06:55
Kilka krótkich, słodkich metod przedłużania na IEnumerable
i IEnumerable<T>
Zrób to dla mnie:
public static IEnumerable Append(this IEnumerable first, params object[] second)
{
return first.OfType<object>().Concat(second);
}
public static IEnumerable<T> Append<T>(this IEnumerable<T> first, params T[] second)
{
return first.Concat(second);
}
public static IEnumerable Prepend(this IEnumerable first, params object[] second)
{
return second.Concat(first.OfType<object>());
}
public static IEnumerable<T> Prepend<T>(this IEnumerable<T> first, params T[] second)
{
return second.Concat(first);
}
Elegancki (no, z wyjątkiem wersji nie-generycznych). Szkoda, że tych metod nie ma w BCL.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-23 16:40:09
No Theenumerable doens not support adding items to items.
"alternatywą", którą masz, jest.
var List = new List(items);
List.Add(otherItem);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-31 02:41:28
Aby dodać drugą wiadomość musisz -
IEnumerable<T> items = new T[]{new T("msg")};
items = items.Concat(new[] {new T("msg2")})
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-17 03:05:34
Nie tylko nie możesz dodawać elementów takich jak stan, ale jeśli dodasz element do List<T>
(lub prawie każdej innej kolekcji nie tylko do odczytu), dla której masz istniejący licznik, licznik jest unieważniany (od tego momentu rzuca InvalidOperationException
).
Jeśli agregujesz wyniki z jakiegoś typu zapytania o dane, możesz użyć metody rozszerzenia Concat
:
Edit: pierwotnie użyłem rozszerzenia Union
w przykładzie, które nie jest do końca poprawne. Moja aplikacja używa go szeroko, aby na pewno nakładające się zapytania nie powielają wyników.
IEnumerable<T> itemsA = ...;
IEnumerable<T> itemsB = ...;
IEnumerable<T> itemsC = ...;
return itemsA.Concat(itemsB).Concat(itemsC);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-31 02:00:27
W. Net Core istnieje metoda Enumerable.Append
, która dokładnie to robi.
Kod źródłowy metody jest dostępny na Githubie..... Warto zajrzeć do realizacji (bardziej wyrafinowanej niż sugestie w innych odpowiedziach):).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-12 19:34:04
Inni już dali świetne wyjaśnienia, dlaczego nie możesz (i nie powinieneś!) możliwość dodawania elementów do IEnumerable
. Dodam tylko, że jeśli chcesz kontynuować kodowanie do interfejsu, który reprezentuje kolekcję i chcesz metody add, powinieneś kodować do ICollection
lub IList
. Jako dodatkowy bonanza, interfejsy te implementują IEnumerable
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-31 02:05:14
Przyszedłem tylko powiedzieć, że oprócz metody rozszerzenia Enumerable.Concat
, wydaje się, że w.NET Core 1.1.1 istnieje inna metoda o nazwie Enumerable.Append
. Ta ostatnia pozwala połączyć pojedynczy element z istniejącą sekwencją. Tak więc odpowiedź Aamola może być również zapisana jako
IEnumerable<T> items = new T[]{new T("msg")};
items = items.Append(new T("msg2"));
Należy jednak pamiętać, że ta funkcja nie zmieni sekwencji wejściowej, po prostu zwraca opakowanie, które umieszcza daną sekwencję i Dołączony element razem.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-10 11:18:00
Dasz radę.
//Create IEnumerable
IEnumerable<T> items = new T[]{new T("msg")};
//Convert to list.
List<T> list = items.ToList();
//Add new item to list.
list.add(new T("msg2"));
//Cast list to IEnumerable
items = (IEnumerable<T>)items;
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-28 19:27:07
Najprostszym sposobem na to jest po prostu
IEnumerable<T> items = new T[]{new T("msg")};
List<string> itemsList = new List<string>();
itemsList.AddRange(items.Select(y => y.ToString()));
itemsList.Add("msg2");
Wtedy możesz zwrócić listę jako IEnumerable również dlatego, że implementuje on interfejs IEnumerable
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-28 11:49:36
Jasne, że możesz (zostawiam twój t-biznes na bok):
public IEnumerable<string> tryAdd(IEnumerable<string> items)
{
List<string> list = items.ToList();
string obj = "";
list.Add(obj);
return list.Select(i => i);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-06 15:26:28