“Somente leitura” Accessor Propriedade em C #
-
03-07-2019 - |
Pergunta
Eu tenho a seguinte classe:
class SampleClass
{
private ArrayList mMyList;
SampleClass()
{
// Initialize mMyList
}
public ArrayList MyList
{
get { return mMyList;}
}
}
Eu quero que os usuários sejam capazes de obter mMyList que é por isso que eu exposto a "pegar" através de uma propriedade no entanto eu não quero mudanças que eles fazem para o objeto (ou seja MyList.Add (nova Classe ());). para fazer o seu caminho de volta para minha classe.
Eu acho que eu posso retornar uma cópia do objeto, mas que pode ser lento e eu estou procurando uma maneira que irá proporcionar um erro em tempo de compilação informando o usuário que não deve esperar para ser capaz de modificar o retornou valor da propriedade.
Isso é possível?
Solução
Com um ArrayList você está bastante limitada porque não há somente leitura classe de coleção não genérico na BCL. A solução rápida e suja é retornar um tipo de IEnumerable.
public IEnumerable MyList
{
get { return mMyList;}
}
Este não vai realmente impedir que alguém lançando a ArrayList, mas não vai permitir edições por padrão tanto
Você pode retornar uma lista efetivamente somente leitura chamando ArrayList.ReadOnly. No entanto, do tipo de retorno é um ArrayList para que o usuário ainda seria capaz de compilar com .Add mas que iria produzir um erro de execução.
Outras dicas
Use a ArrayList.ReadOnly () método para construir e retornar um read-only invólucro em torno da lista. ele não vai copiar a lista, mas simplesmente fazer um read-only invólucro em torno dele. A fim de obter a verificação em tempo de compilação, você provavelmente vai querer voltar a read-only invólucro como IEnumerable como @Jared sugere.
public IEnumerable MyList
{
get { return ArrayList.ReadOnly(mMyList); }
}
Uma coleção que é somente leitura é simplesmente uma coleção com um invólucro que impede a modificação coleção. Se forem feitas alterações ao subjacente a coleção, o read-only coleção reflecte essas alterações.
Este método é um O (1) operação.
Apenas para expandir a resposta de JaredPar. Como ele disse, retornando o campo de apoio real não é completamente seguro, desde que o usuário ainda é capaz de lançar dinamicamente a volta IEnumerable
a um ArrayList
.
Gostaria de escrever algo como isto para ter certeza sem modificações para a lista original são feitas:
public IEnumerable MyList
{
get
{
foreach (object o in mMyList)
yield return o;
}
}
Então, novamente, eu iria probabily também usar uma lista genérica (IEnumerable<T>
) a ser tipo completamente seguro.
Use um ReadOnlyCollection
.
return new ReadOnlyCollection<object>(mMyList)
.
Você também pode fazer o ReadOnlyCollection
um campo, e ele será automaticamente refletir as mudanças na lista subjacente. Esta é a solução mais eficiente.
Se você sabe que mMyList contém apenas um tipo de objeto (por exemplo, não tem nada, mas DateTimes),
você pode retornar um ReadOnlyCollection<DateTime>
(ou algum outro tipo) para a segurança tipo adicional. Se você estiver usando C # 3, você pode simplesmente escrever
return new ReadOnlyCollection<DateTime>(mMyList.OfType<DateTime>().ToArray())
No entanto, isso não vai atualizar automaticamente com a lista subjacente, e também é menos eficiente (Ele irá copiar a lista inteira). A melhor opção é fazer mMyList um List<T>
genérico (por exemplo, um List<DateTime>
)
Você deve envolver o valor de retorno de uma leitura única coleção.
Disponível a partir .NET v2.0
public ArrayList MyList { get; private set; }
Apenas certifique a propriedade como Sealed (ou NotInheritable em VB.NET) e somente leitura, como este:
public sealed readonly ArrayList MyList
{
get { return mMyList;}
}
Também não se esqueça de tornar o campo de apoio como somente leitura:
private readonly ArrayList mMyList;
Mas, para inicializar o valor de mMyList, você deve inicializar só no construtor, como neste exemplo:
public SampleClass()
{
// Initialize mMyList
mMyList = new ArrayList();
}