Veja a definição da classe System.Array
public abstract class Array : IList, ...
Teoricamente, eu deveria ser capaz de escrever esse trecho e ser feliz
int[] list = new int[] {};
IList iList = (IList)list;
Eu também devo chamar qualquer método do iList
ilist.Add(1); //exception here
Minha pergunta não é por que recebo uma exceção, mas por que a matriz implementa o IList ?
c#
arrays
ilist
liskov-substitution-principle
oleksii
fonte
fonte
Respostas:
Como uma matriz permite acesso rápido por índice, e
IList
/IList<T>
is são as únicas interfaces de coleção que suportam isso. Portanto, talvez sua pergunta real seja "Por que não há interface para coleções constantes com indexadores?" E para isso eu não tenho resposta.Também não há interfaces somente leitura para coleções. E sinto falta daqueles ainda mais do que um tamanho constante com a interface de indexadores.
Na IMO, deve haver várias outras interfaces de coleta (genéricas), dependendo dos recursos de uma coleção. E os nomes deveriam ter sido diferentes também,
List
pois algo com um indexador é realmente IMO estúpido.IEnumerable<T>
ICollection<T>
IList<T>
Eu acho que as interfaces de coleção atuais são de design ruim. Mas, como eles têm propriedades informando quais métodos são válidos (e isso faz parte do contrato desses métodos), não infringe o princípio da substituição.
fonte
add
e, portanto, não pode ser substituída por algo que ocorre quando essa capacidade é necessária.IsFixedSize
eIsReadOnly
, definitivamente viola o princípio Tell, Don't Ask e o princípio da menor surpresa . Por que implementar uma interface quando você está lançando exceções para 4 dos 9 métodos?A seção de comentários da documentação para
IList
dizObviamente, as matrizes se enquadram na categoria de tamanho fixo; portanto, pela definição da interface, faz sentido.
fonte
Array
disso, implementaAdd
explicitamente o método, o que reduz o risco de chamá-lo por acidente.IList
que não permita modificação e adição / remoção. Então a documentação não está mais correta. : PPorque nem todos os
IList
s são mutáveis (vejaIList.IsFixedSize
eIList.IsReadOnly
) e as matrizes certamente se comportam como listas de tamanho fixo.Se sua pergunta é realmente "por que ela implementa uma interface não genérica ", a resposta é que elas existiam antes dos genéricos aparecerem.
fonte
IList
própria interface diz que pode não ser mutável. Se fosse de fato garantido para ser mutável e a matriz dito o contrário, em seguida, ele iria quebrar a regra.IList<T>
e não o quebra no caso de não-genéricoIList
: enterprisecraftsmanship.com/2014/11/22/…É um legado que temos desde os tempos em que não estava claro como lidar com coleções somente leitura e se a matriz é ou não somente leitura. Existem sinalizadores IsFixedSize e IsReadOnly na interface IList. O sinalizador IsReadOnly significa que a coleção não pode ser alterada e IsFixedSize significa que a coleção permite a modificação, mas não a adição ou remoção de itens.
Na época do .Net 4.5, estava claro que algumas interfaces "intermediárias" são necessárias para trabalhar com coleções somente leitura,
IReadOnlyCollection<T>
eIReadOnlyList<T>
foram introduzidas.Aqui está uma excelente postagem no blog que descreve os detalhes: Coleções somente leitura no .NET
fonte
A definição da interface IList é "Representa uma coleção não genérica de objetos que podem ser acessados individualmente pelo índice". A matriz satisfaz completamente essa definição, portanto deve implementar a interface. A exceção ao chamar o método Add () é "System.NotSupportedException: Collection era de um tamanho fixo" e ocorreu porque a matriz não pode aumentar sua capacidade dinamicamente. Sua capacidade é definida durante a criação do objeto de matriz.
fonte
Ter uma matriz implementando IList (e transitivamente, ICollection) simplificou o mecanismo Linq2Objects, pois converter o IEnumerable para IList / ICollection também funcionaria para matrizes.
Por exemplo, um Count () acaba chamando Array.Length por baixo do capô, pois é convertido para ICollection e a implementação do array retorna Length.
Sem isso, o mecanismo Linq2Objects não teria tratamento especial para matrizes e apresentaria um desempenho horrível, ou eles precisariam dobrar o código, adicionando tratamento de caso especial para matrizes (como fazem para IList). Eles devem ter optado por fazer o array implementar o IList.
Essa é a minha opinião sobre "Por que".
fonte
Também detalha detalhes da implementação LINQ Últimas verificações para IList, se não implementasse a lista, elas precisariam de 2 verificações que atrasam todas as últimas chamadas ou têm a última em uma matriz recebendo O (N)
fonte