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 ...".
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.