Un compañero de trabajo me preguntó hoy cómo agregar un rango a una colección. Tiene una clase de la que hereda Collection<T>. Hay una propiedad de solo obtención de ese tipo que ya contiene algunos elementos. Quiere agregar los elementos de otra colección a la colección de propiedades. ¿Cómo puede hacerlo de una manera compatible con C # 3? (Tenga en cuenta la restricción sobre la propiedad de solo obtener, que evita soluciones como hacer Unión y reasignar).
Seguro, un foreach con Property. Agregar funcionará. Pero un List<T>AddRange al estilo sería mucho más elegante.
Es bastante fácil escribir un método de extensión:
public static class CollectionHelpers
{
public static void AddRange<T>(this ICollection<T> destination,
IEnumerable<T> source)
{
foreach (T item in source)
{
destination.Add(item);
}
}
}
Pero tengo la sensación de que estoy reinventando la rueda. No encontré nada similar en System.Linqni más en linq .
¿Mal diseño? ¿Solo llamar a Agregar? ¿Falta lo obvio?
fuente

ICollection<T>no parece tener unAddmétodo. msdn.microsoft.com/en-us/library/… Sin embargo,Collection<T>tiene uno.Add(T item)en primer lugar? Parece un enfoque a medias para ofrecer la capacidad de agregar un solo elemento y luego esperar que todas las personas que llaman repitan para agregar más de uno a la vez. Su declaración es ciertamente cierta para,IEnumerable<T>pero me he sentido frustradoICollectionsen más de una ocasión. No estoy en desacuerdo contigo, solo desahogo.Respuestas:
No, esto parece perfectamente razonable. Hay un método
List<T>.AddRange () que básicamente hace esto, pero requiere que su colección sea concretaList<T>.fuente
Intente transmitir a List en el método de extensión antes de ejecutar el bucle. De esa manera, puede aprovechar el rendimiento de List.AddRange.
fuente
asoperador nunca lanzará. Sidestinationno se puede lanzar,listserá nulo y elelsebloque se ejecutará.if (destination is List<T> list)Ya que
.NET4.5si quieres one-liner puedes usarSystem.Collections.GenericForEach.o incluso más corto como
En cuanto al rendimiento, es el mismo que para cada bucle (azúcar sintáctico).
Además , no intentes asignarlo como
la causa
ForEaches nula.Editar: Copiado de los comentarios, la opinión de Lipert sobre ForEach
fuente
ForEachparece que solo se define enList<T>,Collection¿ no ?Recuerda que cada uno
Addcomprobará la capacidad de la colección y la redimensionará cuando sea necesario (más lento). ConAddRange, se configurará la capacidad de la colección y luego se agregarán los elementos (más rápido). Este método de extensión será extremadamente lento, pero funcionará.fuente
Aquí hay una versión un poco más avanzada / lista para producción:
fuente
destinationes una lista deShape, una clase abstracta.sourcees una lista deCircleuna clase heredada.Los C5 Colecciones Biblioteca genérica de clases todo el apoyo del
AddRangemétodo. C5 tiene una interfaz mucho más robusta que realmente expone todas las características de sus implementaciones subyacentes y es compatible con las interfacesSystem.Collections.GenericICollectionyIList, lo que significa queC5las colecciones se pueden sustituir fácilmente como la implementación subyacente.fuente
Puede agregar su rango IEnumerable a una lista y luego establecer ICollection = en la lista.
fuente
O simplemente puede hacer una extensión ICollection como esta:
Usarlo sería como usarlo en una lista:
fuente