Lista somente leitura ou lista não modificável no .NET 4.0

100

Pelo que posso dizer, o .NET 4.0 ainda carece de listas somente leitura. Por que o framework ainda carece dessa funcionalidade? Não é esta uma das peças mais comuns de funcionalidade para design orientado a domínio ?

Uma das poucas vantagens do Java sobre o C # é na forma do método Collections.unmodifiablelist (list) , que parece estar muito atrasado em IList <T> ou List <T>.

Usar IEnumerable<T>é a solução mais fácil para a questão - ToListpode ser usado e devolve uma cópia.

Chris S
fonte
Parece que a única maneira real de ter um verdadeiro somente leitura List<T>é escrever o seu. Não há nenhuma classe interna que eu conheça que ofereça suporte a todos os recursos "somente leitura" prontos List<T>para uso Contains, como consultas LINQ etc.
jrh

Respostas:

146

Você está procurando ReadOnlyCollection, que existe desde .NET2.

IList<string> foo = ...;
// ...
ReadOnlyCollection<string> bar = new ReadOnlyCollection<string>(foo);

ou

List<string> foo = ...;
// ...
ReadOnlyCollection<string> bar = foo.AsReadOnly();

Isso cria uma visualização somente leitura , que reflete as alterações feitas na coleção agrupada.

LukeH
fonte
1
Eu me sinto um pouco estúpido por ter feito esta pergunta agora - e não sei sobre ReadOnlyCollection
Chris S
54
não seja - nem eu, quando fui procurar a mesma coisa e encontrei Sua pergunta
Roland Tepp
9
Essa é uma classe irritantemente difícil de encontrar. Ele está no namespace System.Collections.ObjectModel em vez de System.Collections.Generic, onde eu esperaria encontrá-lo. Suponho que seja porque era onde estava antes de existir o namespace Genérico. Ainda assim, eu esperaria que a classe base permanecesse em ObjectModel e a classe genérica fosse adicionada a Genérico. Suponho que tenham seus motivos, mas acho isso irritante.
BlueMonkMN
5
@BlueMonkMN: Consulte este artigo para descobrir por que ele é separado do namespace Collections.Generic.
Uchitha
7
Mas isso não é uma lista, é uma coleção. Portanto, se você usá-lo, precisará modificar todo o seu código para usar Collection em vez de List.
Roman Zabicki
13

Para quem gosta de usar interfaces: .NET 4.5 adiciona a IReadOnlyListinterface genérica que é implementada por, List<T>por exemplo.

É semelhante IReadOnlyCollectione adiciona uma Itempropriedade do indexador.

Martin
fonte
11

Se o padrão mais comum da lista é iterar por todos os elementos, IEnumerable<T>ou IQueryable<T>pode atuar efetivamente como uma lista somente leitura também.

Ana betts
fonte
4
Se você expor sua List como um IEnumerable, o consumidor poderá simplesmente lançá-la de volta em List e modificá-la.
JulianR
4
Claro, mas não se destina a ser uma medida à prova de balas - você provavelmente também pode ler os campos privados e rastrear a lista original. É mais como descrever a intenção de que permaneça somente leitura.
Ana Betts
5
Você não está modificando a lista original chamando ToList()também, apenas uma cópia
Chris S
Observe que IEnumerablenão é um conjunto completo de métodos "somente leitura", por exemplo, não contém métodos como Contains.
jrh
8

No 2.0, você pode ligar AsReadOnlypara obter uma versão somente leitura da lista. Ou envolva um existente IListem um ReadOnlyCollection<T>objeto.

Paul Alexander
fonte
isso é o equivalente a Collections.unmodifiablelist (lista) que eu estava atrás
Chris S
Perdi isso no .NET 4 porque estava usando um IList <T> em vez de um List <T> verdadeiro. Certifique-se de observar que AsReadOnly ainda está disponível no .NET 4, desde que você esteja lidando com um List <T>.
BlueMonkMN