c# .net immutable-collections

c# - ¿Por qué usar ImmutableList sobre ReadOnlyCollection?



.net immutable-collections (4)

Con una ReadOnlyCollection :

Una colección que es de solo lectura es simplemente una colección con un contenedor que impide modificar la colección; por lo tanto, si se realizan cambios en la colección subyacente, la colección de solo lectura refleja esos cambios.

Esto no puede suceder con una ImmutableList .

.NET 4.5 tiene un nuevo espacio de nombres System.Collections.Immutable

Este paquete proporciona colecciones que son seguras para subprocesos y garantiza que nunca cambiarán sus contenidos, también conocidas como colecciones inmutables.

Estoy confundido. ¿El problema de seguridad de subprocesos ya no está resuelto por la clase ReadOnlyCollection ? ¿Por qué usar ImmutableList lugar?

Sé que también hay una interfaz IReadOnlyList . Eso no resuelve el problema de seguridad del hilo implícitamente, porque otros hilos pueden editar el objeto por otra interfaz.


En escenarios de subprocesos múltiples, tenga en cuenta que las colecciones de solo lectura todavía no son seguras para subprocesos.

De la documentación de ReadOnlyCollection<T> :

... si se realizan cambios en la colección subyacente, la colección de solo lectura refleja esos cambios

Como las colecciones, como List<T> y otras, no son seguras para subprocesos, tampoco lo es la colección de solo lectura.

Importante : Hay algunos casos de esquina que no encontrará explícitamente explicados en MSDN. Algunas de las operaciones que aparentemente solo leen el contenido de una colección, de hecho, están modificando las estructuras internas de la colección. ¿Por qué no se especifica esto? - Una razón obvia es porque es un detalle de implementación que no se refleja en la API. El resultado es que incluso si no modifica la List<T> envuelta en una ReadOnlyCollection<T> , y solo usa getters, ¡el bloqueo aún podría ocurrir en un entorno de subprocesos múltiples!

La conclusión es que las colecciones comunes, incluso cuando se envuelven en una ReadOnlyCollection no se pueden usar en un entorno multiproceso ReadOnlyCollection para usar.

A diferencia de ReadOnlyCollection , las colecciones inmutables garantizan que ninguna de las estructuras internas cambiará una vez que se haya obtenido una referencia a una colección. Tenga en cuenta que estas estructuras aún no son realmente inmutables. Son, en cambio, congelables . Eso significa que la estructura cambiará internamente durante un tiempo hasta que se congele y se devuelva a la persona que llama. Más allá de ese punto, todas las demás llamadas en la colección inmutable solo harán modificaciones fuera de las estructuras accesibles a través de la referencia original.

Conclusión: las colecciones de solo lectura no son seguras para subprocesos; Las colecciones inmutables son seguras para subprocesos.


ReadOnlyCollection<T> no resuelve ninguno de los problemas de seguridad de subprocesos. Es simplemente una envoltura alrededor de Ilist<T> . No expone a los miembros a modificar la colección, pero siempre puede modificarla con la referencia de colección subyacente.

Si se modifica la colección subyacente, no es seguro enumerar ReadOnlyCollection<T> . Si lo hace, obtendrá la misma InvalidOperationException con el mensaje "La colección se modificó; la operación de enumeración puede no ejecutarse ...".

De ReadOnlyCollection

ReadOnlyCollection puede admitir varios lectores al mismo tiempo, siempre que la colección no se modifique. Aun así, enumerar a través de una colección no es intrínsecamente un procedimiento seguro para subprocesos. Para garantizar la seguridad del subproceso durante la enumeración, puede bloquear la colección durante toda la enumeración. Para permitir que varios subprocesos accedan a la colección para leer y escribir, debe implementar su propia sincronización.

ImmutableList por otro lado, es inmutable y, por lo tanto, es inherentemente seguro para subprocesos.


ReadOnlyCollection , como su nombre indica, solo se puede leer.

Por otro lado, puede agregar / eliminar elementos a / de una ImmutableList llamando a sus métodos Add / Remove / Clear , por ejemplo, que devuelven una nueva lista inmutable.