.net .net-4.5 bcl

¿Por qué List<T> implementa IReadOnlyList<T> en.NET 4.5?



.net-4.5 bcl (7)

¿No es cierto que el código que ejecuta IReadOnlyList (Of T) llama a un objeto que implementa esa interfaz suele ejecutar el mismo hilo de ejecución. Eso evita que el objeto se altere por sí mismo, a menos que se ejecute en un hilo diferente de ejecución, pero para esa situación tenemos llamadas de sincronización para resolver eso.

¿Por qué List<T> implementa IReadOnlyList<T> en .NET 4.5?

List<T> no es de solo lectura ...


El hecho de que implementa la interfaz no significa que sea de solo lectura. Pero debido a que implementa la interfaz, ahora puede pasarla a métodos que esperan una IReadOnlyList<T> . Entonces, la forma de verlo es que implementa la interfaz de lista de solo lectura ... junto con algunos métodos de escritura.


IReadOnlyList es un sustituto del concepto de "inmutabilidad de referencia", que se encuentra en C ++ pero no en C #. El equivalente de C ++ es:

void func (T const * t) {...}

o exactamente equivalente, como algunos prefieren:

void func (const T * t) {...}

Dice que la función func no muta el objeto (s) al que su argumento t hace referencia, llamado el "referente" de t. No dice nada sobre si cualquier otro código muta el referente de t, o incluso si puede.

Entonces, la interfaz C # es un sustituto de una construcción compiladora. Por qué C # no tiene el concepto de inmutabilidad de referencia es una pregunta histórica: creo que fue un error, pero ya es demasiado tarde para solucionarlo. Creo que proporcionar el sustituto de la interfaz es bueno. He estado usando una interfaz exactamente igual a IReadOnlyList <> durante años, afortunadamente con otro nombre, IConstList <>. Puedo reemplazar mi uso de IConstList <> con IReadOnlyList <>.


Implementar una interfaz no es lo mismo que "marcarla". List<T> también implementa IEnumerable<T> , pero eso no significa que esté limitado a simplemente enumerarlo.

Agregaron las interfaces de solo lectura para la creación de API, no para que pueda marcar sus tipos de solo lectura con una interfaz. Me permite usar IReadOnlyCollection<T> para los argumentos cuando solo quiero saber el número de elementos en la colección sin enumerarlo, o IReadOnlyList<T> cuando necesito hacer referencia a los elementos en la colección por su índice. Esto es bueno para todos: puedo especificar qué necesito de mi interlocutor y permitir que mi interlocutor utilice el tipo de recopilación que desee, siempre que cumpla con el estándar mínimo establecido a través del tipo de argumento.

Entonces, creo que la pregunta más difícil es: ¿por qué no tendrías List<T> implementar IReadOnlyList<T> ?


Las interfaces IReadOnlyList e IReadOnlyCollection son algo confusas porque no significan que la colección sea de solo lectura, solo que se admite el acceso de solo lectura. De la documentación de MSDN (desplácese hacia abajo a Comentarios)

No se garantiza que el contenido de los elementos de la lista sea de solo lectura.

Un mejor nombre sería IReadable , vea ¿Por qué ICollection genérico no implementa IReadOnlyCollection en .NET 4.5? . Además, esto implica que IList debe heredar IReadOnlyList aunque no lo hace debido a la compatibilidad con versiones anteriores. Consulte ¿Por qué IList<T> hereda de IReadOnlyList<T> ? .


Las interfaces solo describen la funcionalidad que se implementará. No describe la funcionalidad que no se implementará. IReadOnlyList es por lo tanto un nombre de interfaz incorrecto, ya que no puede dictar que la funcionalidad de escritura no se escribirá.

Los métodos / funciones de describir que puede leer el contenido de la lista. La interfaz debería haber sido IReadableList en lugar de IReadOnlyList.


Porque List<T> implementa todos los métodos / propiedades / etc necesarios. (y luego algunos) de IReadOnlyList<T> . Una interfaz es un contrato que dice "puedo hacer al menos estas cosas".

La documentación para IReadOnlyList<T> dice que representa una colección de elementos de solo lectura.

Está bien. No hay métodos de mutación en esa interfaz. Eso es lo que significa "solo lectura", ¿verdad? IReadOnlyList<T> se usa en el modo "típico" (contrato), no como un marker .