.NET 4.5 a un nouvel espace de noms System.Collections.Immutable
Ce package fournit des collections sécurisées pour les threads et garanties de ne jamais modifier leur contenu, également appelées collections immuables.
Je suis confus. Le problème de sécurité des threads n'est-il pas déjà résolu par la classe ReadOnlyCollection ? Pourquoi utiliser ImmutableList à la place?
Je sais qu'il y a aussi une interface IReadOnlyList . Cela ne résout pas implicitement le problème de sécurité des threads, car d'autres threads peuvent modifier l'objet par une autre interface.
Avec un ReadOnlyCollection
:
Une collection en lecture seule est simplement une collection avec un wrapper qui empêche de modifier la collection; par conséquent, si des modifications sont apportées à la collection sous-jacente, la collection en lecture seule reflète ces modifications.
Cela ne peut pas arriver avec un ImmutableList
.
ReadOnlyCollection<T>
ne résout aucun des problèmes de sécurité des threads. Il s'agit simplement d'un wrapper autour de Ilist<T>
. Il n'expose pas aux membres de modifier la collection, mais vous pouvez toujours la modifier avec la référence de collection sous-jacente.
Si la collection sous-jacente est modifiée, il n'est pas sûr d'énumérer le ReadOnlyCollection<T>
. Si vous le faites, vous obtiendrez le même InvalidOperationException
avec le message "La collection a été modifiée; l'opération d'énumération peut ne pas s'exécuter ...".
Un ReadOnlyCollection peut prendre en charge plusieurs lecteurs simultanément, tant que la collection n'est pas modifiée. Même ainsi, l'énumération via une collection n'est pas intrinsèquement une procédure thread-safe. Pour garantir la sécurité des threads pendant l'énumération, vous pouvez verrouiller la collection pendant toute l'énumération. Pour permettre à la collection d'être accessible par plusieurs threads pour la lecture et l'écriture, vous devez implémenter votre propre synchronisation.
ImmutableList
d'autre part est immuable et donc intrinsèquement sûr pour les threads.
ReadOnlyCollection
, comme son nom l'indique, ne peut être lu.
D'un autre côté, vous pouvez ajouter/supprimer des éléments à/d'un ImmutableList
en appelant ses méthodes Add
/Remove
/Clear
, par exemple, qui retourner une nouvelle liste immuable.
Dans les scénarios multi-thread, sachez que les collections en lecture seule ne sont toujours pas thread-safe.
Du ReadOnlyCollection<T>
Documentation:
... si des modifications sont apportées à la collection sous-jacente, la collection en lecture seule reflète ces modifications
Depuis les collections, comme List<T>
et d'autres, ne sont pas sûrs pour les threads, de même que la collection en lecture seule.
Important: Il existe des cas d'angle que vous ne trouverez pas explicitement expliqués dans MSDN. Certaines des opérations qui ne semblent lire que le contenu d'une collection modifient en fait les structures internes de la collection. Pourquoi cela n'est-il pas spécifié? - Une raison évidente est qu'il s'agit d'un détail d'implémentation qui ne reflète pas l'API. Le résultat est que même si vous ne modifiez pas le List<T>
enveloppé dans un ReadOnlyCollection<T>
, et n'utilisez que des getters, le crash peut toujours se produire dans un environnement multi-thread!
En bout de ligne, les collections courantes, même lorsqu'elles sont enveloppées dans un ReadOnlyCollection
, ne peuvent pas être utilisées dans un environnement multithread dès le départ.
Contrairement à ReadOnlyCollection
, les collections immuables garantissent qu'aucune des structures internes ne changera jamais après l'obtention d'une référence à une collection. Notez que ces structures ne sont toujours pas vraiment immuables. Ils sont, à la place, congelables . Cela signifie que la structure changera en interne pendant un certain temps jusqu'à ce qu'elle soit gelée et renvoyée à l'appelant. Au-delà de ce point, tous les autres appels sur la collection immuable ne feront que des modifications en dehors des structures accessibles via la référence d'origine.
Conclusion: les collections en lecture seule ne sont pas thread-safe; les collections immuables sont thread-safe.