Pergunta

A minha pergunta como título acima. Por exemplo,

IEnumerable<T> items = new T[]{new T("msg")};
items.ToList().Add(new T("msg2"));

mas afinal de contas ele só tem 1 item dentro.

Podemos ter um método como items.Add(item)?

como o List<T>

Foi útil?

Solução

Você não pode, porque IEnumerable<T> não representa necessariamente uma coleção para os itens que podem ser adicionados. Na verdade, ele não representa necessariamente uma coleção em tudo! Por exemplo:

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??

O que você pode fazer, porém, é criar um new objeto IEnumerable (de tipo não especificado), que, quando enumerados, irá fornecer todos os itens do antigo, além de alguns dos seus próprios. Você usa Enumerable.Concat para isso:

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

Este não vai mudar o objeto array (você não pode inserir itens para a matrizes, pelo menos). Mas ele irá criar um novo objeto que irá listar todos os itens na matriz, em seguida, "Foo". Além disso, esse novo objeto irá acompanhar as mudanças na matriz (ou seja, sempre que enumerá-lo, você verá os valores atuais dos itens).

Outras dicas

O tipo IEnumerable<T> não suporta tais operações. O objetivo da interface IEnumerable<T> é permitir que um consumidor para visualizar o conteúdo de uma coleção. Não modificar os valores.

Quando você faz operações como .ToList (). Add () você está criando um novo List<T> e adicionando um valor a essa lista. Não tem nenhuma conexão com a lista original.

O que você pode fazer é usar o método Add extensão para criar um novo IEnumerable<T> com o valor acrescentado.

items = items.Add("msg2");

Mesmo neste caso não vai modificar o objeto IEnumerable<T> originais. Isto pode ser verificado, mantendo uma referência a ele. Por exemplo

var items = new string[]{"foo"};
var temp = items;
items = items.Add("bar");

Após este conjunto de operações a temperatura variável vão apenas referência a um enumeráveis ??com um elemento único "foo" no conjunto de valores, enquanto os itens fará referência a um enumeráveis ??diferente com valores de "Foo" e "barra".

Editar

Eu contstantly esquecer que Add não é um método de extensão típica em IEnumerable<T> porque é um dos primeiros que eu acabam definindo. Aqui é

public static IEnumerable<T> Add<T>(this IEnumerable<T> e, T value) {
  foreach ( var cur in e) {
    yield return cur;
  }
  yield return value;
}

Você já pensou em usar ICollection<T> ou IList<T> as interfaces em vez disso, eles existem para a mesma razão que você quer ter um método Add em um IEnumerable<T>.

IEnumerable<T> é usado para 'marca' um tipo como sendo ... bem, enumeráveis ??ou apenas uma seqüência de itens sem necessariamente fazer quaisquer garantias de se os reais apoios objeto subjacente adição / remoção de itens. Lembre-se também que essas interfaces implementar IEnumerable<T> de modo a obter métodos de todas as extensões que você começa com IEnumerable<T> também.

Um par suma, os métodos de extensão doces em IEnumerable e IEnumerable<T> fazer isso por mim:

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);
}

Elegant (bem, exceto para as versões não-genéricos). Pena que esses métodos não são na BCL.

Sem o IEnumerable não suporta adicionar itens a ele.

Você 'alternativa' é:

var List = new List(items);
List.Add(otherItem);

Em .net Core, há uma Enumerable.Append método que faz exatamente isso.

O código fonte do método é disponível no GitHub. .... A implementação (mais sofisticado do que as sugestões em outras respostas) é olhar a pena :).

Para adicionar segunda mensagem você precisa -

IEnumerable<T> items = new T[]{new T("msg")};
items = items.Concat(new[] {new T("msg2")})

Não só você não pode adicionar itens como você estado, mas se você adicionar um item a uma List<T> (ou praticamente qualquer outro não-somente leitura coleção) que você tem um enumerador existente para, o enumerador é invalidado (joga InvalidOperationException a partir de então).

Se você está agregando resultados de algum tipo de consulta de dados, você pode usar o método de extensão Concat:

Edit: Eu originalmente usado a extensão Union no exemplo, que não é realmente correta. Meu aplicativo usa extensivamente para se certificar de sobreposição consultas fazer resultados não duplicados.

IEnumerable<T> itemsA = ...;
IEnumerable<T> itemsB = ...;
IEnumerable<T> itemsC = ...;
return itemsA.Concat(itemsB).Concat(itemsC);

Eu só vim aqui para dizer que, além do método de extensão Enumerable.Concat, parece haver outro método chamado Enumerable.Append em .NET Núcleo 1.1.1. Este último permite que você concatenar um único item a uma seqüência existente. Então, a resposta de Aamol também pode ser escrito como

IEnumerable<T> items = new T[]{new T("msg")};
items = items.Append(new T("msg2"));

Ainda assim, por favor nota que esta função não vai mudar a seqüência de entrada, apenas retornar um invólucro que colocar a sequência dada e o item anexado juntos.

Outros já têm dado grandes explicações a respeito de porque você não pode (e não! Deve) ser capaz de adicionar itens a uma IEnumerable. Vou apenas acrescentar que, se você está olhando para continuar codificação para uma interface que representa uma coleção e quer um método add, você deve código para ICollection ou IList . Como uma bonança acrescentou, essas interfaces implementar IEnumerable.

você pode fazer isso.

//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;

A maneira mais fácil de fazer isso é simplesmente

IEnumerable<T> items = new T[]{new T("msg")};
List<string> itemsList = new List<string>();
itemsList.AddRange(items.Select(y => y.ToString()));
itemsList.Add("msg2");

Depois, você pode lista de regresso se IEnumerable também porque ele implementa a interface IEnumerable

Claro, você pode (eu estou deixando o seu T-business lado):

public IEnumerable<string> tryAdd(IEnumerable<string> items)
{
    List<string> list = items.ToList();
    string obj = "";
    list.Add(obj);

    return list.Select(i => i);
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top