Wie kann ich ein Element zu einer IEnumerable -Auflistung hinzufügen?

Meine Frage als Titel oben. Beispielsweise,

IEnumerable items = new T[]{new T("msg")}; items.ToList().Add(new T("msg2")); 

aber immerhin hat es nur 1 Stück drin.

Können wir eine Methode wie items.Add(item) ?

wie die List

IEnumerable ist nicht möglich, da IEnumerable nicht unbedingt eine Sammlung darstellt, der Elemente hinzugefügt werden können. Tatsächlich repräsentiert es nicht unbedingt eine Sammlung! Beispielsweise:

 IEnumerable ReadLines() { string s; do { s = Console.ReadLine(); yield return s; } while (s != ""); } IEnumerable lines = ReadLines(); lines.Add("foo") // so what is this supposed to do?? 

Sie können jedoch ein neues IEnumerable Objekt (eines nicht angegebenen Typs) erstellen, das beim Aufzählen alle Elemente des alten sowie einige eigene Elemente enthält. Sie verwenden Enumerable.Concat dafür:

  items = items.Concat(new[] { "foo" }); 

Dadurch wird das Array-Objekt nicht geändert (Sie können Objekte sowieso nicht in Arrays einfügen). Aber es wird ein neues Objekt erstellen, das alle Elemente im Array auflistet, und dann “Foo”. Darüber hinaus wird dieses neue Objekt die Änderungen im Array verfolgen (dh wenn Sie es aufzählen, sehen Sie die aktuellen Werte von Elementen).

Der Typ IEnumerable unterstützt solche Operationen nicht. Der Zweck der IEnumerable -Schnittstelle besteht darin, einem Benutzer das Anzeigen des Inhalts einer Sammlung zu ermöglichen. Die Werte nicht ändern.

Bei Operationen wie .ToList (). Add () erstellen Sie eine neue List und fügen dieser Liste einen Wert hinzu. Es hat keine Verbindung zur ursprünglichen Liste.

Sie können mit der Erweiterungsmethode Add ein neues IEnumerable mit dem hinzugefügten Wert erstellen.

 items = items.Add("msg2"); 

Auch in diesem Fall wird das ursprüngliche IEnumerable -Objekt nicht IEnumerable . Dies kann überprüft werden, indem ein Verweis darauf gehalten wird. Beispielsweise

 var items = new string[]{"foo"}; var temp = items; items = items.Add("bar"); 

Nach dieser Menge von Operationen referenziert die Variable temp immer noch nur auf ein Aufzählungselement mit einem einzelnen Element “foo” in der Menge von Werten, während Elemente auf ein anderes aufzählbares Element mit den Werten “foo” und “bar” verweisen.

BEARBEITEN

Ich vergesse ständig, dass Add keine typische Erweiterungsmethode für IEnumerable weil es eine der ersten ist, die ich am Ende definiere. Hier ist es

 public static IEnumerable Add(this IEnumerable e, T value) { foreach ( var cur in e) { yield return cur; } yield return value; } 

Haben Sie darüber nachgedacht, ICollection – oder IList -Schnittstellen zu verwenden, existieren sie nur deshalb, weil Sie eine ‘Add’ -Methode für ein IEnumerable verwenden möchten. IEnumerable wird verwendet, um einen Typ als … gut .. aufzählbar oder nur als eine Abfolge von Elementen zu markieren, ohne notwendigerweise zu garantieren, ob das reale zugrunde liegende Objekt das Hinzufügen / Entfernen von Elementen unterstützt. Denken Sie auch daran, dass diese Schnittstellen IEnumerable implementieren, damit Sie auch alle Erweiterungsmethoden erhalten, die Sie mit IEnumerable erhalten.

Ein paar kurze, süße Erweiterungsmethoden auf IEnumerable und IEnumerable tun es für mich:

 public static IEnumerable Append(this IEnumerable first, params object[] second) { return first.OfType().Concat(second); } public static IEnumerable Append(this IEnumerable first, params T[] second) { return first.Concat(second); } public static IEnumerable Prepend(this IEnumerable first, params object[] second) { return second.Concat(first.OfType()); } public static IEnumerable Prepend(this IEnumerable first, params T[] second) { return second.Concat(first); } 

Elegant (gut, außer für die nicht-generischen Versionen). Schade, dass diese Methoden nicht in der BCL sind.

Nein, IEnumerable unterstützt das Hinzufügen von Objekten nicht.

Eine “Alternative”, die Sie haben, ist.

 var List = new List(items); List.Add(otherItem); 

Um eine zweite Nachricht hinzuzufügen, müssen Sie

 IEnumerable items = new T[]{new T("msg")}; items = items.Concat(new[] {new T("msg2")}) 

Sie können nicht nur Elemente hinzufügen, die Sie angeben, aber wenn Sie ein Element zu einer List (oder einer anderen nicht schreibgeschützten Auflistung) hinzufügen, für die Sie einen Enumerator besitzen, wird der Enumerator ungültig (throws InvalidOperationException von da an).

Wenn Sie Ergebnisse einer Art von Datenabfrage aggregieren, können Sie die Concat Erweiterungsmethode verwenden:

Bearbeiten: Ich habe ursprünglich die Union Erweiterung in dem Beispiel verwendet, die nicht wirklich korrekt ist. Meine Anwendung verwendet es umfassend, um sicherzustellen, dass überlappende Abfragen Ergebnisse nicht duplizieren.

 IEnumerable itemsA = ...; IEnumerable itemsB = ...; IEnumerable itemsC = ...; return itemsA.Concat(itemsB).Concat(itemsC); 

In .net Core gibt es eine Methode Enumerable.Append , die genau das tut.

Der Quellcode der Methode ist auf GitHub verfügbar. …. Die Implementierung (komplizierter als die Vorschläge in anderen Antworten) ist einen Blick wert :).

Andere haben bereits gute Erklärungen dafür gegeben, warum Sie Elemente zu einem IEnumerable nicht hinzufügen können (und sollten!). Ich füge nur hinzu, dass Sie, wenn Sie fortfahren, an einer Schnittstelle zu codieren, die eine Sammlung darstellt und eine add-Methode möchte, in ICollection oder IList ICollection IList . Als zusätzliche Bonanza implementieren diese Schnittstellen IEnumerable .

Ich komme nur hierher, um zu sagen, dass neben der Erweiterungsmethode ” Enumerable.Concat eine andere Methode namens ” Enumerable.Append in .NET Core 1.1.1 zu existieren scheint. Letzteres ermöglicht es Ihnen, ein einzelnes Objekt mit einer bestehenden Sequenz zu verketten. So kann Aamols Antwort auch als geschrieben werden

 IEnumerable items = new T[]{new T("msg")}; items = items.Append(new T("msg2")); 

Beachten Sie jedoch, dass diese function die Eingabesequenz nicht ändert, sondern nur einen Wrapper zurückgibt, der die angegebene Sequenz und das angefügte Element zusammenfügt.

du kannst das.

 //Create IEnumerable IEnumerable items = new T[]{new T("msg")}; //Convert to list. List list = items.ToList(); //Add new item to list. list.add(new T("msg2")); //Cast list to IEnumerable items = (IEnumerable)items; 

Der einfachste Weg, das zu tun, ist einfach

 IEnumerable items = new T[]{new T("msg")}; List itemsList = new List(); itemsList.AddRange(items.Select(y => y.ToString())); itemsList.Add("msg2"); 

Dann können Sie die Liste auch als IEnumerable zurückgeben, da sie die IEnumerable-Schnittstelle implementiert

Sicher, du kannst (ich verlasse dein T-Geschäft zur Seite):

 public IEnumerable tryAdd(IEnumerable items) { List list = items.ToList(); string obj = ""; list.Add(obj); return list.Select(i => i); }