2010-11-15 15 views
11

Me sorprende ver que no parece haber un método para agregar un solo elemento a una colección IEnumerable.¿Cuál es la mejor manera de agregar un solo elemento a una colección IEnumerable?

¿Cómo puedo agregar un elemento único a una colección IEnumerable?

+0

posible duplicado de [? ¿Cómo puedo agregar un elemento a una colección IEnumerable ] (http : //stackoverflow.com/questions/1210295/how-can-i-add-an-item-to-a-ienumerablet-collection) – nawfal

Respuesta

23

Realmente no se puede añadir elementos a un IEnumerable como se supone que debe ser de sólo lectura. Su mejor apuesta es o bien algo como:

return new List<Foo>(enumerable){ new Foo() }; 

o

return enumerable.Concat(new [] { new Foo() }); 
6

puede concatenar con una matriz Singleton:

IEnumerable xs; 
xs.Concat(new[]{x}); 
19

El punto de IEnumerable es que es una colección de estilo tirón de sólo lectura. Si lo desea, puede simular un complemento al hacer algo como esto:

public static IEnumerable<T> Add<T>(this IEnumerable<T> source, T additionalItem) 
{ 
    foreach(var item in source) 
    { 
     yield return item; 
    } 

    yield return additionalItem; 
} 
+2

Sugiero humildemente nombrar este método como "Concat" porque siento que comunica la intención del método mejor que "Agregar", que tiene un significado bastante fuerte cuando se trata de la colección s. – GuiSim

+3

'Append' es aún mejor. Concat siente ganas de unirse con algo similar, mientras que Add/Append se siente como suplementario con algo (aunque Add se siente menos perezoso) .. – nawfal

+0

De alguna manera este método parece mejor que el de Jonnii, el rendimiento parece más natural cuando se trata de enumerable –

0

IEnumerable está diseñada para iterar sobre los elementos. No siempre tiene una colección como respaldo. Además, mientras recorre una colección, no puede modificar la colección.

Si necesita actualizar su colección mientras la itera, debe hacer una copia antes de iniciar su ciclo foreach. El método ToList() de LINQ es una buena forma de hacerlo.

0

Puede que no sea la respuesta que está buscando, pero el uso de las clases de colección genéricas siempre parece resolver este tipo de problemas para mí. La mayoría de ellos tiene un método .Add (T).

2

IEnumerable es una colección de solo lectura, ICollection proporciona una colección mutable con Agregar y quitar.

Sin embargo, puede crear un nuevo IEnumerable contienen todos los elementos de la IEnumerable original y un elemento nuevo, mediante la concatenación de 2 listas:

var newCollection = original.Concat(new[]{element}); 
6

me gustaría señalar que algunas de las otras respuestas aquí que IEnumerable no es una colección de solo lectura, no es una colección en absoluto. Es una interfaz que define cómo se puede iterar una colección.

Si desea agregar objetos, debe agregar los objetos a su clase de colección concreta o al menos usar una interfaz diferente.

4

Teniendo en cuenta lo que otros han dicho acerca de no ser realmente capaz de "agregar" a un enumerable, todavía puede simular la adición. De hecho, argumentaría que puedes "agregar" un elemento a una secuencia transformando la secuencia en una nueva secuencia que de hecho "contiene" el elemento (¡simplemente itera sobre la nueva secuencia si no me crees!) .

También puede expresar un solo elemento como algo numerable así:

//ToEnumerable might not be the best name here 
public static IEnumerable<T> ToEnumerable<T>(this T item) 
{ 
    return Enumerable.Repeat(item,1); 
} 

o

public static IEnumerable<T> ToEnumerable<T>(this T item) 
{ 
    yield return item; 
} 

Entonces puede "añadir" un elemento a una enumerable como esto:

var items = GetSomeItems(); 

var itemsWithNewItemOnEnd = items.Concat(somenewitem.ToEnumerable()); 

var itemsWithNewItemAtStart = somenewitem.ToEnumerable().Concat(items); 

Incluso puede insertar el elemento en alguna otra ubicación en la secuencia de esta manera (suponiendo que sepa la posición después de la cual desea insertarlo):

var itemsWithNewItemInserted = items.Take(5).Concat(somenewitem.ToEnumerable()).Concat(items.Skip(5)); 

Después de finalizar su operación (es decir, usted ha manipulado la secuencia de modo que "contiene" lo que desea que contenga), es probable que desee hacer una matriz o lista de la secuencia a través de los métodos toArray o ToList:

var itemsWithNewItemInserted = items.Take(5).Concat(somenewitem.ToEnumerable()).Concat(items.Skip(5)).ToList(); 

Ahora itemsWithNewItemInserted es una lista que contiene todos los elementos deseados de la lista original, con los nuevos elementos insertados en el medio.

Jugar con secuencias demasiado parecidas (tomar, saltar, insertar, etc.) puede costarle tiempo porque cada método de extensión agregado (Take, Skip, etc.) puede hacer que la secuencia se itere varias veces, pero el la sintaxis de comprensión de lista facilita la expresión de operaciones que parecen ser un poco más intrincadas mediante la iteración convencional.

nuevo, aquí hay algunos enlaces que hablan de expresar artículos individuales como IEnumerable:

Passing a single item as IEnumerable<T>

Is there a neater linq way to 'Union' a single item?

+0

Creo que ToEnumerable (con Concat) es la mejor solución. –

Cuestiones relacionadas