it-swarm.com.de

Wie kann ich einer IEnumerable <T> -Sammlung ein Element hinzufügen?

Meine Frage als Titel oben. Zum Beispiel,

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

aber immerhin hat es nur 1 Artikel im Inneren.

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

wie der List<T>

372
ldsenow

Dies ist nicht möglich, da IEnumerable<T> nicht unbedingt eine Sammlung darstellt, zu der Elemente hinzugefügt werden können. Tatsächlich handelt es sich nicht unbedingt um eine Sammlung! Zum Beispiel:

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??

Sie können jedoch ein neuesIEnumerable -Objekt (von nicht angegebenem Typ) erstellen, das bei Aufzählung alle Elemente des alten Typs sowie einige Ihrer eigenen bereitstellt. Sie verwenden Enumerable.Concat dafür:

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

Dies ändert das Array-Objekt nicht (Sie können sowieso keine Elemente in Arrays einfügen). Es wird jedoch ein neues Objekt erstellt, das alle Elemente im Array und dann "Foo" auflistet. Darüber hinaus wird dieses neue Objekt Änderungen im Array nachverfolgen (d. H. Wann immer Sie es aufzählen, werden die aktuellen Werte von Elementen angezeigt).

442
Pavel Minaev

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

Wenn Sie Operationen wie .ToList (). Add () ausführen, erstellen Sie einen neuen List<T> und fügen dieser Liste einen Wert hinzu. Es besteht keine Verbindung zur ursprünglichen Liste.

Sie können die Add-Erweiterungsmethode verwenden, um einen neuen IEnumerable<T> mit dem Mehrwert zu erstellen.

items = items.Add("msg2");

Auch in diesem Fall wird das ursprüngliche Objekt IEnumerable<T> nicht geändert. Dies kann durch einen Verweis darauf überprüft werden. Zum Beispiel

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

Nach diesem Satz von Operationen verweist die Variable temp nur noch auf eine Aufzählung mit einem einzelnen Element "foo" im Wertesatz, während Elemente auf eine andere Aufzählung mit den Werten "foo" und "bar" verweisen.

EDIT

Ich vergesse immer wieder, dass Add keine typische Erweiterungsmethode für IEnumerable<T> ist, weil es eine der ersten ist, die ich am Ende definiere. Hier ist es

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

Haben Sie in Betracht gezogen, stattdessen ICollection<T> oder IList<T> Schnittstellen zu verwenden, existieren diese aus dem Grund, dass Sie eine Add-Methode auf einem IEnumerable<T> haben möchten.

IEnumerable<T> wird verwendet, um einen Typ als ... gut, aufzählbar oder nur als eine Folge von Elementen zu 'markieren', ohne notwendigerweise zu garantieren, dass das tatsächliche zugrunde liegende Objekt das Hinzufügen/Entfernen von Elementen unterstützt. Denken Sie auch daran, dass diese Schnittstellen IEnumerable<T> implementieren, sodass Sie auch alle Erweiterungsmethoden erhalten, die Sie mit IEnumerable<T> erhalten.

52
Abhijeet Patel

Ein paar kurze, süße Erweiterungsmethoden für IEnumerable und IEnumerable<T> erledigen das für mich:

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);
}

Elegant (naja, bis auf die nicht generischen Versionen). Schade, dass diese Methoden nicht in der BCL enthalten sind.

31
Will

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

Ihre "Alternative" ist:

var List = new List(items);
List.Add(otherItem);
18
Paul van Brenk

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

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

14
JanDotNet

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

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

Sie können nicht nur keine Elemente wie angegeben hinzufügen, sondern der Enumerator wird ungültig, wenn Sie ein Element zu einer List<T> -Auflistung (oder so ziemlich jeder anderen nicht schreibgeschützten Sammlung) hinzufügen, für die Sie einen vorhandenen Enumerator haben InvalidOperationException von da an).

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

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

IEnumerable<T> itemsA = ...;
IEnumerable<T> itemsB = ...;
IEnumerable<T> itemsC = ...;
return itemsA.Concat(itemsB).Concat(itemsC);
8
Sam Harwell

Ich komme hierher, um zu sagen, dass es in .NET Core 1.1.1 neben der Erweiterungsmethode Enumerable.Concat eine andere Methode namens Enumerable.Append zu geben scheint. Letzteres ermöglicht es Ihnen, ein einzelnes Element mit einer vorhandenen Sequenz zu verknüpfen. So kann Aamols Antwort auch als geschrieben werden

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

Beachten Sie jedoch, dass diese Funktion die Eingabesequenz nicht ändert, sondern lediglich einen Wrapper zurückgibt, der die angegebene Sequenz und das angehängte Element zusammenfügt.

6
CXuesong

Andere haben bereits großartige Erklärungen gegeben, warum Sie nicht in der Lage sein können (und sollten!), Einem IEnumerable Elemente hinzuzufügen. Ich möchte nur hinzufügen, dass Sie, wenn Sie weiterhin eine Schnittstelle codieren möchten, die eine Auflistung darstellt, und eine Add-Methode möchten, auf ICollection oder IList codieren sollten. Als zusätzliches Bonanza implementieren diese Schnittstellen IEnumerable.

4
jason

du kannst das.

//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;
1
Lrodriguez84

Am einfachsten geht das ganz einfach

IEnumerable<T> items = new T[]{new T("msg")};
List<string> itemsList = new List<string>();
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

0
Juha Sinkkonen