c# - lista - ¿Cómo puedo agregar un artículo a una colección IEnumerable<T>?
read ienumerable c# (13)
Claro que puedes (estoy dejando tu negocio de T a un lado):
public IEnumerable<string> tryAdd(IEnumerable<string> items)
{
List<string> list = items.ToList();
string obj = "";
list.Add(obj);
return list.Select(i => i);
}
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 la List<T>
El tipo IEnumerable<T>
no admite tales operaciones. El propósito de la IEnumerable<T>
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 de extensión Agregar para crear un nuevo IEnumerable<T>
con el valor agregado.
items = items.Add("msg2");
Incluso en este caso, no modificará el objeto IEnumerable<T>
. Esto se puede verificar manteniendo una referencia a él. Por ejemplo
var items = new string[]{"foo"};
var temp = items;
items = items.Add("bar");
Después de este conjunto de operaciones, la variable temp todavía 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 "barra".
EDITAR
Continuamente olvido que Agregar no es un método de extensión típico en IEnumerable<T>
porque es uno de los primeros que IEnumerable<T>
definir. Aquí está
public static IEnumerable<T> Add<T>(this IEnumerable<T> e, T value) {
foreach ( var cur in e) {
yield return cur;
}
yield return value;
}
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 ver la implementación (más sofisticada que las sugerencias en otras respuestas) :).
La forma más fácil de hacerlo es simplemente
IEnumerable<T> items = new T[]{new T("msg")};
List<string> itemsList = new List<string>();
itemsList.AddRange(items.Select(y => y.ToString()));
itemsList.Add("msg2");
Entonces puede devolver la lista como IEnumerable también porque implementa la interfaz IEnumerable
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:
IEnumerable<string> ReadLines()
{
string s;
do
{
s = Console.ReadLine();
yield return s;
} while (s != "");
}
IEnumerable<string> lines = ReadLines();
lines.Add("foo") // so what is this supposed to do??
Sin embargo, lo que puede hacer es crear un nuevo objeto IEnumerable
(de tipo no especificado) que, cuando se enumere, proporcionará todos los elementos del anterior, más algunos de los suyos. Usted usa Enumerable.Concat
para eso:
items = items.Concat(new[] { "foo" });
Esto no cambiará el objeto de la matriz (de todos modos, no puede insertar elementos en las matrices). Pero creará un nuevo objeto que listará 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).
No solo no puede agregar elementos como su estado, sino que si agrega un elemento a una List<T>
(o casi a cualquier otra colección que no sea de solo lectura) para la que tiene un enumerador existente, el enumerador se invalida (lanza InvalidOperationException
a partir de entonces).
Si está agregando resultados de algún tipo de consulta de datos, puede usar el método de extensión Concat
:
Edición: originalmente usé la extensión Union
en el ejemplo, lo cual no es realmente correcto. Mi aplicación lo usa ampliamente para asegurarse de que las consultas superpuestas no dupliquen los resultados.
IEnumerable<T> itemsA = ...;
IEnumerable<T> itemsB = ...;
IEnumerable<T> itemsC = ...;
return itemsA.Concat(itemsB).Concat(itemsC);
No, IEnumerable no admite agregar elementos a él.
Tu ''alternativa'' es:
var List = new List(items);
List.Add(otherItem);
Otros ya han dado grandes explicaciones acerca de por qué no puede (¡y no debería!) Poder agregar elementos a un IEnumerable
. Solo agregaré que si desea continuar la codificación a una interfaz que representa una colección y desea un método de adición, debe codificar a ICollection<T> o IList<T> . Como una bonanza adicional, estas interfaces implementan IEnumerable
.
Para agregar el segundo mensaje necesitas:
IEnumerable<T> items = new T[]{new T("msg")};
items = items.Concat(new[] {new T("msg2")})
Puedes hacerlo.
//Create IEnumerable
IEnumerable<T> items = new T[]{new T("msg")};
//Convert to list.
List<T> list = items.ToList();
//Add new item to list.
list.add(new T("msg2"));
//Cast list to IEnumerable
items = (IEnumerable<T>)items;
Si ha considerado utilizar IList<T> interfaces ICollection<T> o IList<T> , existen por el motivo que desea tener un método ''Agregar'' en un IEnumerable <T>. IEnumerable <T> se usa para "marcar" un tipo como ... bueno ... enumerable o simplemente una secuencia de elementos sin necesariamente ofrecer ninguna garantía de si el objeto subyacente real admite la adición / eliminación de elementos. También recuerde que estas interfaces implementan IEnumerable <T> para que también obtenga todos los métodos de extensiones que obtiene con IEnumerable <T>.
Solo vengo aquí para decir que, aparte del método de extensión Enumerable.Concat
, parece haber otro método llamado Enumerable.Append
en .NET Core 1.1.1. Este último le permite concatenar un solo elemento a una secuencia existente. Así que la respuesta de Aamol también se puede escribir como
IEnumerable<T> items = new T[]{new T("msg")};
items = items.Append(new T("msg2"));
Aún así, tenga en cuenta que esta función no cambiará la secuencia de entrada, simplemente devolverá un contenedor que reunió la secuencia dada y el elemento adjunto.
Un par de cortos y dulces métodos de extensión en IEnumerable
e IEnumerable<T>
hacen por mí:
public static IEnumerable Append(this IEnumerable first, params object[] second)
{
return first.OfType<object>().Concat(second);
}
public static IEnumerable<T> Append<T>(this IEnumerable<T> first, params T[] second)
{
return first.Concat(second);
}
public static IEnumerable Prepend(this IEnumerable first, params object[] second)
{
return second.Concat(first.OfType<object>());
}
public static IEnumerable<T> Prepend<T>(this IEnumerable<T> first, params T[] second)
{
return second.Concat(first);
}
Elegante (bueno, salvo las versiones no genéricas). Lástima que estos métodos no estén en el BCL.