Minha pergunta como título acima. Por exemplo,
IEnumerable<T> items = new T[]{new T("msg")};
items.ToList().Add(new T("msg2"));
mas afinal ele tem apenas 1 item dentro.
Podemos ter um método como items.Add(item)
?
como o List<T>
c#
list
ienumerable
ldsenow
fonte
fonte
IEnumerable<T>
destina-se apenas à consulta de coleções. É a espinha dorsal da estrutura LINQ. É sempre uma abstração de alguma outra coleção comoCollection<T>
,List<T>
ouArray
. A interface fornece apenas umGetEnumerator
método que retorna uma instânciaIEnumerator<T>
que permite a caminhada da coleção estendida, um item de cada vez. Os métodos de extensão LINQ são limitados por essa interface.IEnumerable<T>
foi projetado para ser lido somente porque pode representar uma agregação de partes de várias coleções.IList<T>
vez deIEnumerable<T>
:IList<T> items = new T[]{new T("msg")}; items.Add(new T("msg2"));
Respostas:
Você não pode, porque
IEnumerable<T>
não representa necessariamente uma coleção à qual itens podem ser adicionados. De fato, não representa necessariamente uma coleção! Por exemplo:O que você pode fazer, no entanto, é criar um novo
IEnumerable
objeto (de tipo não especificado), que, quando enumerado, fornecerá todos os itens do antigo, além de alguns dos seus. Você usaEnumerable.Concat
para isso:Isso não altera o objeto da matriz (você não pode inserir itens nas matrizes, de qualquer maneira). Mas ele criará um novo objeto que listará todos os itens da matriz e, em seguida, "Foo". Além disso, esse novo objeto acompanhará as alterações na matriz (ou seja, sempre que você a enumerar, você verá os valores atuais dos itens).
fonte
Concat
seja chamado repetidamente em um loop; e se for, você tem problemas maiores de qualquer maneira, porque toda vez queConcat
obtém mais uma camada de enumerador - portanto, ao final, a chamada únicaMoveNext
resultará em uma cadeia de chamadas igual em comprimento ao número de iterações.IEnumerable<T>
no C #, incluindo sobrecarga,operator+
já queConcat
(a propósito, você sabe que no VB é possível indexarIEnumerable
como se fosse um array - ele usaElementAt
sob o capô): connect.microsoft.com / VisualStudio / feedback /… . Se também recebermos mais duas sobrecargasConcat
para pegar um único item à esquerda e à direita, isso reduziria a digitação paraxs +=x
- então vá cutucar Mads (Torgersen) para priorizar isso no C # 5.0 :)O tipo
IEnumerable<T>
não suporta essas operações. O objetivo daIEnumerable<T>
interface é permitir que um consumidor visualize o conteúdo de uma coleção. Não para modificar os valores.Ao executar operações como .ToList (). Add (), você cria um novo
List<T>
e adiciona um valor a essa lista. Não tem conexão com a lista original.O que você pode fazer é usar o método Add extension para criar um novo
IEnumerable<T>
com o valor agregado.Mesmo nesse caso, ele não modificará o
IEnumerable<T>
objeto original . Isso pode ser verificado mantendo uma referência a ele. Por exemploApós esse conjunto de operações, a variável temp ainda fará referência a um enumerável com um único elemento "foo" no conjunto de valores, enquanto os itens farão referência a um enumerável diferente com os valores "foo" e "bar".
EDITAR
Eu sempre esqueço que o Add não é um método de extensão típico,
IEnumerable<T>
porque é um dos primeiros que eu acabo definindo. Aqui estáfonte
Concat
:)Add
entanto, eu não chamaria isso , porqueAdd
praticamente qualquer outro tipo de .NET (não apenas coleções) modifica a coleção no local. TalvezWith
? Ou poderia ser apenas mais uma sobrecarga deConcat
.Concat
sobrecarga provavelmente seria uma escolha melhor, poisAdd
geralmente implica mutabilidade.return e.Concat(Enumerable.Repeat(value,1));
?Você já pensou em usar interfaces
ICollection<T>
ouIList<T>
, em vez disso, elas existem pelo mesmo motivo que você deseja ter umAdd
método em umaIEnumerable<T>
.IEnumerable<T>
é usado para 'marcar' um tipo como sendo ... bem, enumerável ou apenas uma sequência de itens sem necessariamente garantir que o objeto subjacente real suporte a adição / remoção de itens. Lembre-se também de que essas interfaces são implementadasIEnumerable<T>
para que você obtenha todos os métodos de extensão com osIEnumerable<T>
quais também se relaciona.fonte
Alguns métodos de extensão curtos
IEnumerable
eIEnumerable<T>
agradáveis estão disponíveis para mim:Elegante (bem, exceto para as versões não genéricas). Pena que esses métodos não estão no BCL.
fonte
ToString()
, pois captura mais detalhes do erro. Eu acho que você não estavainclude System.Linq;
no topo do seu arquivo, mas quem sabe? Tente descobrir por conta própria, crie um protótipo mínimo que exiba o mesmo erro, se você não puder, e peça ajuda em uma pergunta.No .net Core, existe um método
Enumerable.Append
que faz exatamente isso.O código fonte do método está disponível no GitHub. .... A implementação (mais sofisticada do que as sugestões em outras respostas) vale a pena dar uma olhada :).
fonte
Não, o IEnumerable não oferece suporte à adição de itens.
Você 'alternativa' é:
fonte
Para adicionar a segunda mensagem, você precisa -
fonte
Não apenas você não pode adicionar itens como você declara, mas se você adicionar um item a
List<T>
(ou praticamente qualquer outra coleção não somente leitura) para a qual você tem um enumerador existente, o enumerador será invalidado (será lançado aInvalidOperationException
partir de então).Se você estiver agregando resultados de algum tipo de consulta de dados, poderá usar o
Concat
método de extensão:Editar: originalmente usei a
Union
extensão no exemplo, o que não é realmente correto. Meu aplicativo o usa extensivamente para garantir que as consultas sobrepostas não duplicem os resultados.fonte
Eu só vim aqui para dizer que, além do
Enumerable.Concat
método de extensão, parece haver outro método nomeadoEnumerable.Append
no .NET Core 1.1.1. O último permite concatenar um único item para uma sequência existente. Portanto, a resposta de Aamol também pode ser escrita comoAinda assim, observe que esta função não altera a sequência de entrada, apenas retorna um wrapper que coloca a sequência fornecida e o item anexado.
fonte
Outros já deram grandes explicações sobre por que você não pode (e não deveria!) Ser capaz de adicionar itens a um
IEnumerable
. Acrescentarei apenas que, se você deseja continuar codificando para uma interface que representa uma coleção e deseja um método add, deve codificar paraICollection
orIList
. Como uma vantagem adicional, essas interfaces são implementadasIEnumerable
.fonte
você consegue fazer isso.
fonte
A maneira mais fácil de fazer isso é simplesmente
Em seguida, você pode retornar a lista como IEnumerable também porque implementa a interface IEnumerable
fonte
Se você criar seu objeto como
IEnumerable<int> Ones = new List<int>();
Então você pode fazer((List<int>)Ones).Add(1);
fonte
Claro, você pode (estou deixando seu negócio de lado):
fonte