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.Linq
ni más en linq .
¿Mal diseño? ¿Solo llamar a Agregar? ¿Falta lo obvio?
fuente
ICollection<T>
no parece tener unAdd
mé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 frustradoICollections
en 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
as
operador nunca lanzará. Sidestination
no se puede lanzar,list
será nulo y elelse
bloque se ejecutará.if (destination is List<T> list)
Ya que
.NET4.5
si quieres one-liner puedes usarSystem.Collections.Generic
ForEach.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
ForEach
es nula.Editar: Copiado de los comentarios, la opinión de Lipert sobre ForEach
fuente
ForEach
parece que solo se define enList<T>
,Collection
¿ no ?Recuerda que cada uno
Add
comprobará 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
destination
es una lista deShape
, una clase abstracta.source
es una lista deCircle
una clase heredada.Los C5 Colecciones Biblioteca genérica de clases todo el apoyo del
AddRange
mé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.Generic
ICollection
yIList
, lo que significa queC5
las 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