¿Por qué array implementa IList?

Consulte la definición de System.Array class

public abstract class Array : IList, ... 

Teóricamente, debería poder escribir este fragmento y ser feliz

 int[] list = new int[] {}; IList iList = (IList)list; 

También debería poder llamar a cualquier método de iList

  ilist.Add(1); //exception here 

Mi pregunta no es por qué recibo una excepción, sino más bien ¿por qué Array implementa IList ?

Debido a que una matriz permite el acceso rápido por índice, e IList / IList es la única interfaz de recostackción que lo admite. Así que tal vez su verdadera pregunta es “¿Por qué no hay interfaz para colecciones constantes con indexadores?” Y a eso no tengo respuesta.

Tampoco hay interfaces de solo lectura para colecciones. Y me faltan esos incluso más que una interfaz de tamaño constante con indexadores.

OMI debe haber varias interfaces de recostackción más (genéricas) según las características de una colección. Y los nombres deberían haber sido diferentes también, List para algo con un indexador es realmente IMO estúpido.

  • Just Enumeration IEnumerable
  • Solo lectura pero sin indexador (.Count, .Contains, …)
  • Redimensionable pero sin indexador, es decir, configurado como (Agregar, Eliminar, …) ICollection actual ICollection
  • Readonly con indexador (indexador, indexof, …)
  • Tamaño constante con indexador (indexador con setter)
  • Tamaño variable con indexador (Insertar, …) actual IList

Creo que las interfaces de colección actuales son mal diseño. Pero dado que tienen propiedades que le dicen qué métodos son válidos (y esto es parte del contrato de estos métodos) no rompe el principio de sustitución.

La sección de comentarios de la documentación de IList dice

IList es un descendiente de la interfaz ICollection y es la interfaz base de todas las listas no genéricas. Las implementaciones de IList se dividen en tres categorías: de solo lectura, de tamaño fijo y de tamaño variable . Un IList de solo lectura no se puede modificar. Un IList de tamaño fijo no permite la adición o eliminación de elementos, pero permite la modificación de elementos existentes. Un IList de tamaño variable permite agregar, eliminar y modificar elementos.

Obviamente, las matrices caen en la categoría de tamaño fijo, por lo que la defunción de la interfaz tiene sentido.

Porque no todos los IList son mutables (vea IList.IsFixedSize e IList.IsReadOnly ), y los arrays ciertamente se comportan como listas de tamaño fijo.

Si su pregunta es realmente “¿por qué implementa una interfaz no genérica? “, Entonces la respuesta es que existían antes de que llegaran los generics.

Es un legado que tenemos desde el momento en que no estaba claro cómo lidiar con las colecciones de solo lectura y si Array es o no de solo lectura. Hay indicadores IsFixedSize e IsReadOnly en la interfaz IList. La bandera IsReadOnly significa que la colección no se puede cambiar en absoluto e IsFixedSize significa que la colección permite la modificación, pero no la adición o eliminación de elementos.

En el momento de .Net 4.5, estaba claro que se requieren algunas interfaces “intermedias” para trabajar con colecciones de solo lectura, por lo que se IReadOnlyCollection e IReadOnlyList .

Aquí hay una gran publicación de blog que describe los detalles: colecciones de solo lectura en .NET

La definición de la interfaz IList es “Representa una colección no genérica de objetos a los que se puede acceder individualmente por índice”. La matriz satisface por completo esta definición, por lo que debe implementar la interfaz. La excepción al llamar al método Add () es “System.NotSupportedException: Collection era de un tamaño fijo” y se produjo porque la matriz no puede boost su capacidad de forma dinámica. Su capacidad se define durante la creación del objeto de matriz.