¿Cómo puedo añadir un artículo a una colecciónumumerable?


Mi pregunta como título anterior. 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>

Author: Abel, 2009-07-31

13 answers

No se puede, porque IEnumerable<T> no representa necesariamente una colección a la que se puedan agregar elementos. De hecho, no necesariamente representa 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??

Lo que puede hacer, sin embargo, es crear un nuevo IEnumerable objeto (de tipo no especificado), que, cuando se enumera, proporcionará todos los elementos del anterior, más algunos de los suyos. Usa Enumerable.Concat para eso:

 items = items.Concat(new[] { "foo" });

Esto no cambiará el objeto array (no puede insertar elementos en a arrays, de todos modos). Pero creará un nuevo objeto que enumerará todos los elementos en la matriz, y luego "Foo". Además, ese nuevo objeto hará un seguimiento de los cambios en el array (es decir, cada vez que lo enumere, verá los valores actuales de los elementos).

 391
Author: Pavel Minaev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-12 21:04:06

El tipo IEnumerable<T> no admite tales operaciones. El propósito de la interfaz IEnumerable<T> es permitir que un consumidor vea el contenido de una colección. No modificar los valores.

Cuando haces operaciones como .ToList().Add () estás creando un nuevo List<T> y añadiendo un valor a esa lista. No tiene conexión con la lista original.

Lo que puede hacer es usar el método Add extension para crear un nuevo IEnumerable<T> con el valor agregado.

items = items.Add("msg2");

Incluso en este caso no modifique el objeto original 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 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

Me olvido contstantly que Agregar no es un método de extensión típico en IEnumerable<T> porque es uno de los primeros que termino 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;
}
 76
Author: JaredPar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-31 02:05:56

¿Ha considerado usar ICollection o IList interfaces en su lugar, existen por la misma razón que desea tener un método 'Add' en unEnumerable. IEnumerable se utiliza para "marcar" un tipo como el ser ...bien.. enumerable o simplemente una secuencia de elementos sin hacer necesariamente ninguna garantía de si el objeto subyacente real admite la adición / eliminación de elementos. También recuerde que estas interfaces implementaerableumerable para que obtenga todas las extensiones métodos que también obtienes con .

 45
Author: Abhijeet Patel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-05-27 16:06:55

Un par de métodos de extensión cortos y dulces en IEnumerable y IEnumerable<T> hazlo 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, a excepción de las versiones no genéricas). Lástima que estos métodos no están en el BCL.

 28
Author: Will,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-23 16:40:09

No elerableumerable no admite la adición de elementos.

Una 'alternativa' que tienes es.

var List = new List(items);
List.Add(otherItem);
 13
Author: Paul van Brenk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-31 02:41:28

Para añadir un segundo mensaje es necesario -

IEnumerable<T> items = new T[]{new T("msg")};
items = items.Concat(new[] {new T("msg2")})
 10
Author: Aamol,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-17 03:05:34

No solo no puede agregar elementos como lo indica, sino que si agrega un elemento a una List<T> (o prácticamente a cualquier otra colección que no sea de solo lectura) para la que tenga un enumerador existente, el enumerador se invalida (arroja 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:

Editar: Originalmente usé la extensión Union en el ejemplo, que no es realmente correcta. Mi aplicación lo utiliza ampliamente para hacer seguro que las consultas superpuestas no duplican los resultados.

IEnumerable<T> itemsA = ...;
IEnumerable<T> itemsB = ...;
IEnumerable<T> itemsC = ...;
return itemsA.Concat(itemsB).Concat(itemsC);
 8
Author: Sam Harwell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-31 02:00:27

En.net Core, hay un método Enumerable.Append que hace exactamente eso.

El código fuente del método está disponible en GitHub..... La implementación (más sofisticada que las sugerencias en otras respuestas) vale la pena echar un vistazo :).

 6
Author: JanDotNet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-12 19:34:04

Otros ya han dado grandes explicaciones con respecto a por qué no se puede (y no debe!) ser capaz de añadir elementos a un IEnumerable. Solo agregaré que si está buscando continuar codificando a una interfaz que represente una colección y desea un método add, debe codificar a ICollection o IList. Como una bonanza añadida, estas interfaces implementan IEnumerable.

 4
Author: jason,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-31 02:05:14

Solo vengo a 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. Esto ú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, solo devuelve un envoltorio que une la secuencia dada y el elemento adjunto.

 3
Author: CXuesong,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-10 11:18:00

Puedes hacer esto.

//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;
 1
Author: Lrodriguez84,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-28 19:27:07

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 usted puede devolver la lista como IEnumerable también porque implementa la interfaz IEnumerable

 0
Author: Juha Sinkkonen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-28 11:49:36

Claro, usted puede (estoy dejando su T-negocio 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);
}
 -8
Author: Just N Observer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-06 15:26:28