Es gibt keine AddRange()
Methode für IList<T>
.
Wie kann ich eine Liste von Elementen zu einem hinzufügen, IList<T>
ohne Elemente zu durchlaufen und die Add()
Methode zu verwenden?
Es gibt keine AddRange()
Methode für IList<T>
.
Wie kann ich eine Liste von Elementen zu einem hinzufügen, IList<T>
ohne Elemente zu durchlaufen und die Add()
Methode zu verwenden?
Antworten:
AddRange
ist auf definiert List<T>
, nicht die Schnittstelle.
Sie können die Variable als List<T>
anstelle von deklarieren IList<T>
oder List<T>
in umwandeln, um Zugriff auf zu erhalten AddRange
.
((List<myType>)myIList).AddRange(anotherList);
Dies ist keine gute Vorgehensweise (siehe Kommentare unten), da es sich IList<T>
möglicherweise nicht um einen handelt List<T>
, sondern um einen anderen Typ, der die Schnittstelle implementiert hat und möglicherweise keine AddRange
Methode hat. In diesem Fall werden Sie nur herausfinden, wann Ihr Code eine auslöst Ausnahme zur Laufzeit.
Wenn Sie also nicht sicher sind, dass der Typ tatsächlich ein Typ ist List<T>
, sollten Sie nicht versuchen, ihn zu verwenden AddRange
.
Eine Möglichkeit besteht darin, den Typ mit den Operatoren is oder as zu testen (seit C # 7).
if(myIList is List<T>)
{
// can cast and AddRange
}
else
{
// iterate with Add
}
List<T>
(oder, wenn dies für Sie keine gute Wahl ist, die Besetzung dort durchführen, wo Sie AddRange
sie lokalisieren müssen - dies ist eine sehr kostengünstige Operation ).
InvalidCastException
bei etwas anderem als List<T>
(z. B. Array) auslöst .
Wenn Sie sich den c # -Quellcode für List ansehen, hat List.AddRange () Optimierungen, die eine einfache Schleife nicht adressiert. Eine Erweiterungsmethode sollte daher einfach überprüfen, ob die IList eine Liste ist, und in diesem Fall die native AddRange () verwenden.
Beim Stöbern im Quellcode sehen Sie, dass die .NET-Leute ähnliche Dinge in ihren eigenen Linq-Erweiterungen für Dinge wie .ToList () tun (wenn es sich um eine Liste handelt, setzen Sie sie um ... andernfalls erstellen Sie sie).
public static class IListExtension
{
public static void AddRange<T>(this IList<T> list, IEnumerable<T> items)
{
if (list == null) throw new ArgumentNullException(nameof(list));
if (items == null) throw new ArgumentNullException(nameof(items));
if (list is List<T> asList)
{
asList.AddRange(items);
}
else
{
foreach (var item in items)
{
list.Add(item);
}
}
}
}
list
zu List<T>
zwei Mal hier. Eines davon könnte mit dem as
Schlüsselwort optimiert werden .
if (list is List<T> castedList) { castedList.AddRange(items); }
Sie könnten so etwas tun:
IList<string> oIList1 = new List<string>{"1","2","3"};
IList<string> oIList2 = new List<string>{"4","5","6"};
IList<string> oIList3 = oIList1.Concat(oIList2).ToList();
Im Grunde genommen würden Sie also die Concat()
Erweiterung verwenden und ToList()
eine ähnliche Funktionalität wie erhalten AddRange()
.
Enumerable.Concat
implementiert wird System.Linq.Enumerable
und der Rückgabewert dieser Methode lautet IEnumerable<TSource>
. Daher sollte er meines Erachtens nicht zurückgesetzt werden. IList<TSource>
Aufgrund von Implementierungsdetails, die wir nicht kennen, ohne den Quellcode zu überprüfen, wird möglicherweise etwas anderes zurückgegeben. Es gibt jedoch keine Garantie dafür, dass sich nichts ändert. Daher muss bei der Unterstützung mehrerer .NET-Versionen besondere Aufmerksamkeit geschenkt werden.
Sie können auch eine Erweiterungsmethode wie die folgende schreiben:
internal static class EnumerableHelpers
{
public static void AddRange<T>(this IList<T> collection, IEnumerable<T> items)
{
foreach (var item in items)
{
collection.Add(item);
}
}
}
Verwendung:
IList<int> collection = new int[10]; //Or any other IList
var items = new[] {1, 4, 5, 6, 7};
collection.AddRange(items);
Was immer noch über Elemente iteriert, aber Sie müssen die Iteration nicht jedes Mal schreiben oder umwandeln, wenn Sie sie aufrufen.
Eine andere Antwort mit LINQ, vorausgesetzt, Sie fügen eine hinzu List<T>
oder können sie aufrufen ToList()
:
IEnumerable<string> toAdd = new string[] {"a", "b", "c"};
IList<string> target = new List<string>();
toAdd.ToList().ForEach(target.Add);
Concat
, wie @Self_Taught_Programmer antwortete .