Mi pregunta como título arriba. Por ejemplo,
IEnumerable<T> items = new T[]{new T("msg")};
items.ToList().Add(new T("msg2"));
pero después de todo, solo tiene 1 elemento dentro.
¿Podemos tener un método como items.Add(item)
?
como el List<T>
c#
list
ienumerable
ldsenow
fuente
fuente
IEnumerable<T>
está destinado solo a consultar colecciones. Es la columna vertebral del marco LINQ. Siempre es una abstracción de alguna otra colección comoCollection<T>
,List<T>
oArray
. La interfaz solo proporciona unGetEnumerator
método que devuelve una instancia deIEnumerator<T>
que permite recorrer la colección extendida un elemento a la vez. Los métodos de extensión LINQ están limitados por esta interfaz.IEnumerable<T>
está diseñado para ser leído solo porque puede representar una agregación de partes de múltiples colecciones.IList<T>
lugar deIEnumerable<T>
:IList<T> items = new T[]{new T("msg")}; items.Add(new T("msg2"));
Respuestas:
No puede, porque
IEnumerable<T>
no representa necesariamente una colección a la que se pueden agregar elementos. De hecho, ¡no representa necesariamente una colección en absoluto! Por ejemplo:Sin embargo, lo que puede hacer es crear un nuevo
IEnumerable
objeto (de tipo no especificado) que, cuando se enumera, proporcionará todos los elementos del anterior, más algunos propios. UsasEnumerable.Concat
para eso:Esto no cambiará el objeto de matriz (de todos modos, no puede insertar elementos en las matrices). Pero creará un nuevo objeto que enumerará todos los elementos de la matriz y luego "Foo". Además, ese nuevo objeto hará un seguimiento de los cambios en la matriz (es decir, cada vez que lo enumere, verá los valores actuales de los elementos).
fuente
Concat
se llame repetidamente en un ciclo; y si es así, tiene problemas más grandes de todos modos, porque cada vez queConcat
obtiene una capa más de enumerador, por lo que al final de la misma, la llamada únicaMoveNext
dará como resultado una cadena de llamadas de igual longitud que el número de iteraciones.IEnumerable<T>
en C #, incluida la sobrecargaoperator+
comoConcat
(por cierto, ¿sabes que en VB, puedes indexarIEnumerable
como si fuera una matriz? Se usaElementAt
bajo el capó): connect.microsoft.com / VisualStudio / feedback /… . Si también obtenemos dos sobrecargas másConcat
para tomar un solo elemento tanto a la izquierda como a la derecha, esto reduciría el tipeo paraxs +=x
, así que ve a meter a Mads (Torgersen) para priorizar esto en C # 5.0 :)El tipo
IEnumerable<T>
no admite tales operaciones. El propósito de laIEnumerable<T>
interfaz es permitir que un consumidor vea el contenido de una colección. No modificar los valores.Cuando realiza operaciones como .ToList (). Add (), está creando una nueva
List<T>
y agregando un valor a esa lista. No tiene conexión con la lista original.Lo que puede hacer es usar el método Agregar extensión para crear uno nuevo
IEnumerable<T>
con el valor agregado.Incluso en este caso no modificará el
IEnumerable<T>
objeto original . Esto se puede verificar manteniendo una referencia a él. Por ejemploDespués de este conjunto de operaciones, la variable temp solo hará referencia a un enumerable con un solo elemento "foo" en el conjunto de valores, mientras que los elementos harán referencia a un enumerable diferente con los valores "foo" y "bar".
EDITAR
Continuamente olvido que Agregar no es un método de extensión típico
IEnumerable<T>
porque es uno de los primeros que termino definiendo. Aquí estáfuente
Concat
:)Add
embargo, no lo llamaría porqueAdd
prácticamente en cualquier otro tipo .NET (no solo en colecciones) muta la colección en el lugar. Tal vezWith
? O incluso podría ser solo otra sobrecarga deConcat
.Concat
sobrecarga probablemente sería una mejor opción, ya queAdd
generalmente implica mutabilidad.return e.Concat(Enumerable.Repeat(value,1));
?¿Ha considerado usar interfaces
ICollection<T>
oIList<T>
, en cambio, existen por la misma razón que desea tener unAdd
método en unIEnumerable<T>
.IEnumerable<T>
se usa para 'marcar' un tipo como ... bueno, enumerable o simplemente una secuencia de elementos sin necesariamente garantizar si el objeto subyacente real admite la adición / eliminación de elementos. También recuerde que estas interfaces se implementanIEnumerable<T>
para que también obtenga todos los métodos de extensiones que obtieneIEnumerable<T>
.fuente
Un par de métodos de extensión cortos y dulces
IEnumerable
yIEnumerable<T>
hazlo por mí:Elegante (bueno, excepto las versiones no genéricas). Lástima que estos métodos no están en el BCL.
fuente
ToString()
sobre, ya que captura más detalles de error. Supongo que no lo hicisteinclude System.Linq;
en la parte superior de tu archivo, pero ¿quién sabe? Intenta resolverlo por tu cuenta, crea un prototipo mínimo que muestre el mismo error si no puedes y luego pide ayuda en una pregunta.En .net Core, hay un método
Enumerable.Append
que hace exactamente eso.El código fuente del método está disponible en GitHub. .... Vale la pena echarle un vistazo a la implementación (más sofisticada que las sugerencias en otras respuestas) :).
fuente
No, el IEnumerable no admite agregarle elementos.
Su 'alternativa' es:
fuente
Para agregar un segundo mensaje necesita:
fuente
No solo no puede agregar elementos como
List<T>
dice , sino que si agrega un elemento a una (o prácticamente cualquier otra colección que no sea de solo lectura) para la que tiene un enumerador existente, el enumerador se invalida (se lanza aInvalidOperationException
partir de ese momento).Si está agregando resultados de algún tipo de consulta de datos, puede usar el
Concat
método de extensión:Editar: Originalmente usé la
Union
extensión en el ejemplo, que no es realmente correcta. Mi aplicación lo utiliza ampliamente para asegurar que las consultas superpuestas no dupliquen los resultados.fuente
Solo vine a decir que, aparte del
Enumerable.Concat
método de extensión, parece haber otro método nombradoEnumerable.Append
en .NET Core 1.1.1. Este último le permite concatenar un solo elemento a una secuencia existente. Entonces la respuesta de Aamol también se puede escribir comoAún así, tenga en cuenta que esta función no cambiará la secuencia de entrada, solo devolverá un contenedor que juntará la secuencia dada y el elemento adjunto.
fuente
Otros ya han dado excelentes explicaciones sobre por qué no puede (y no debería) poder agregar elementos a un
IEnumerable
. Solo agregaré que si desea continuar codificando en una interfaz que representa una colección y desea un método de agregar, debe codificarICollection
oIList
. Como una bonanza adicional, se implementan estas interfacesIEnumerable
.fuente
Puedes hacerlo.
fuente
La forma más fácil de hacerlo es simplemente
Entonces puede devolver la lista como IEnumerable también porque implementa la interfaz IEnumerable
fuente
Si crea su objeto como
IEnumerable<int> Ones = new List<int>();
Entonces puede hacer((List<int>)Ones).Add(1);
fuente
Claro, puedes (estoy dejando de lado tu negocio T):
fuente