no hay AddRange()
método para IList<T>
.
¿Cómo puedo agregar una lista de elementos a IList<T>
sin iterar a través de elementos y usar el Add()
método?
fuente
no hay AddRange()
método para IList<T>
.
¿Cómo puedo agregar una lista de elementos a IList<T>
sin iterar a través de elementos y usar el Add()
método?
AddRange
se define en List<T>
, no la interfaz.
Puede declarar la variable como en List<T>
lugar de IList<T>
o convertirla List<T>
en para obtener acceso a AddRange
.
((List<myType>)myIList).AddRange(anotherList);
Esta no es una buena práctica (vea los comentarios a continuación), ya que IList<T>
puede que no sea un List<T>
, pero algún otro tipo que implementó la interfaz y puede que no tenga un AddRange
método; en tal caso, solo lo descubrirá cuando su código arroje un excepción en tiempo de ejecución.
Por lo tanto, a menos que sepa con certeza que el tipo es de hecho List<T>
, no debería intentar usarlo AddRange
.
Una forma de hacerlo es probando el tipo con los operadores is o como (desde C # 7).
if(myIList is List<T>)
{
// can cast and AddRange
}
else
{
// iterate with Add
}
Concat
Emite o usa LINQ , como respondió @Self_Taught_Programmer .List<T>
(o, si esta no es una buena opción para usted, hacer el reparto donde necesitaAddRange
para mantenerlo localizado - es una operación de muy bajo costo ).InvalidCastException
si se usa en cualquier otra cosa que no seaList<T>
(matriz, por ejemplo).Si observa el código fuente de C # para List , creo que List.AddRange () tiene optimizaciones que un simple bucle no aborda. Por lo tanto, un método de extensión simplemente debe verificar si IList es una Lista, y si es así, use su AddRange () nativo.
Al hurgar en el código fuente, ve que la gente de .NET hace cosas similares en sus propias extensiones Linq para cosas como .ToList () (si es una lista, envíelo ... de lo contrario, créelo).
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); } } } }
fuente
list
aList<T>
dos veces aquí. Uno de los cuales podría optimizarse con laas
palabra clave.if (list is List<T> castedList) { castedList.AddRange(items); }
Podrías hacer algo como esto:
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();
Entonces, básicamente, usaría la
Concat()
extensión yToList()
obtendría una funcionalidad similar aAddRange()
.Fuente
fuente
Enumerable.Concat
está implementado porSystem.Linq.Enumerable
y el valor de retorno de ese método esIEnumerable<TSource>
, por lo que creo que no debería devolverseIList<TSource>
, podría devolver algo más debido a los detalles de implementación que no conocemos sin verificar el código fuente. aunque no hay garantía de que no cambie, por lo que se debe prestar especial atención al admitir varias versiones.También puede escribir un método de extensión como este:
internal static class EnumerableHelpers { public static void AddRange<T>(this IList<T> collection, IEnumerable<T> items) { foreach (var item in items) { collection.Add(item); } } }
Uso:
IList<int> collection = new int[10]; //Or any other IList var items = new[] {1, 4, 5, 6, 7}; collection.AddRange(items);
Que todavía está iterando sobre elementos, pero no tiene que escribir la iteración o lanzar cada vez que lo llama.
fuente
Otra respuesta usando LINQ, siempre que lo que está agregando sea un
List<T>
o pueda llamarloToList()
:IEnumerable<string> toAdd = new string[] {"a", "b", "c"}; IList<string> target = new List<string>(); toAdd.ToList().ForEach(target.Add);
fuente
var var1 = output.listDepartment1 var var2 = output.listDepartment2 var1.AddRange(var2); var list = var1;
fuente