2015-05-11 11 views
33

.NET 4.5 ha un nuovo spazio dei nomi System.Collections.ImmutablePerché utilizzare ImmutableList su ReadOnlyCollection?

Questo pacchetto fornisce collezioni che sono thread-safe e garantito per non cambiare il loro contenuto, noto anche come collezioni immutabili.

Sono confuso. Il problema di sicurezza dei thread non è già stato risolto dalla classe ReadOnlyCollection? Perché utilizzare ImmutableList?


So che c'è anche un IReadOnlyList interface. Ciò non risolve implicitamente il problema di sicurezza del thread, poiché altri thread possono modificare l'oggetto con un'altra interfaccia.

+1

Questo post sembra spiegarlo abbastanza bene "http://blog.slaks.net/2013-06-11/readonly-vs-immutable/" – Damian

+1

Solo per l'infomration 'System.Collections.Immutable' deve essere installato tramite il gestore di pacchetti nuget. Ho dovuto farlo in un progetto di targeting. NET Framework 4.6.2. – RBT

risposta

42

Con ReadOnlyCollection: Una collezione

che è di sola lettura semplicemente un insieme con un involucro che impedisce la modifica della raccolta; pertanto, se le modifiche vengono apportate alla raccolta sottostante, la raccolta di sola lettura riflette le modifiche di .

Questo non può accadere con un ImmutableList.

+5

Suggerirei che la caratteristica più importante delle collezioni immutabili è il modo in cui vengono manipolate creando nuove collezioni immutabili e il sottostante efficiente meccanismo di "copia su scrittura". Pertanto le altre due risposte sembrano essere più rilevanti per me. – koloman

+0

L'immutabilità è una grande bugia almeno in C# .Net. Non sono sicuro di altri linguaggi di programmazione. In C# anche con 'ImmutableList' chiunque può passare attraverso un percorso non gestito e modificare il contenuto di quella posizione di memoria senza la conoscenza di CLR. Ma sì, finché tutte le parti si attengono alle leggi offerte dalla piattaforma .Net, possiamo tranquillamente supporre che ImmutableList sia effettivamente immutabile. – RBT

+6

@RBT è lo stesso per qualsiasi programma - se il codice è in esecuzione nello stesso processo, il sistema operativo non ti impedirà di cambiare nulla –

9

ReadOnlyCollection, come suggerisce il nome, può essere letto solo.

D'altra parte, è possibile aggiungere/rimuovere elementi da/per un ImmutableList chiamando i suoi Add/Remove/Clear metodi, per esempio, che restituiscono un nuovo elenco immutabile.

+5

Aggiungo che questo rende 'ImmutableList <>' molto simile ad un 'STRING'. – xanatos

+0

@xanatos, o per qualsiasi tipo di valore (implementato correttamente). – dcastro

18

ReadOnlyCollection<T> non risolve nessuno dei problemi di sicurezza del filo. È semplicemente un involucro intorno a Ilist<T>. Non espone i membri a modificare la raccolta, ma è sempre possibile modificarla con il riferimento di raccolta sottostante.

Se la raccolta sottostante viene modificata, non è sicuro enumerare ReadOnlyCollection<T>. Se lo fai, otterrai lo stesso InvalidOperationException con il messaggio "La raccolta è stata modificata, l'operazione di enumerazione potrebbe non essere eseguita ...".

Da ReadOnlyCollection<T>

Un ReadOnlyCollection può supportare più lettori simultaneamente, come a quando la raccolta non viene modificato. Anche così, enumerare attraverso una collezione non è intrinsecamente una procedura thread-safe. Per garantire la sicurezza del thread durante l'enumerazione, è possibile bloccare la raccolta durante l' l'intera enumerazione. Per consentire l'accesso alla raccolta tramite più thread per la lettura e la scrittura, è necessario implementare la propria sincronizzazione .

ImmutableList d'altra parte è immutabile e quindi intrinsecamente thread safe.

0

In scenari multi-thread, si noti che le raccolte di sola lettura non sono ancora thread-safe.

Dalla documentazione ReadOnlyCollection<T>:

... se vengono apportate modifiche alla raccolta sottostante, la collezione di sola lettura riflette questi cambiamenti

Dal collezioni, come List<T> e altri, sono non thread-safe, quindi non è la raccolta di sola lettura.

Importante: ci sono alcuni casi d'angolo che non troverete esplicitamente spiegato in MSDN. Alcune delle operazioni che apparentemente leggono solo il contenuto di una raccolta, stanno infatti modificando le strutture interne della raccolta. Perché questo non è specificato? - Una ragione ovvia è perché si tratta di un dettaglio di implementazione che non riflette sull'API. Il risultato è che anche se non si modifica List<T> avvolto in un ReadOnlyCollection<T> e si utilizzano solo getter, l'arresto anomalo potrebbe ancora verificarsi in ambiente a più thread!

La linea di fondo è che le raccolte comuni, anche se racchiuse in un ReadOnlyCollection non possono essere utilizzate in ambienti multi-threaded fuori dalla scatola.

Diversamente da ReadOnlyCollection, le raccolte non modificabili garantiscono che nessuna delle strutture interne cambierà mai dopo aver ottenuto un riferimento a una raccolta. Nota che queste strutture non sono ancora veramente immutabili. Sono, invece, freezable. Ciò significa che la struttura cambierà internamente per un po 'finché non sarà congelata e restituita al chiamante. Oltre quel punto, tutte le altre chiamate sulla collezione immutabile effettueranno solo modifiche al di fuori delle strutture accessibili attraverso il riferimento originale.

Conclusione: le raccolte di sola lettura sono non thread-safe; le collezioni immutabili sono thread-safe.

Problemi correlati