2012-04-19 12 views
31

Ho trovato la classe ConditionalWeakTable<TKey,TValue> nella mia ricerca di IDictionary che utilizza riferimenti deboli, come suggerito nelle risposte here e here.Se ConditionalWeakTable dovrebbe essere utilizzato <TKey, TValue> per scopi non del compilatore?

C'è a definitive MSDN article che ha introdotto la classe e in cui si afferma:

È possibile trovare la classe ... nello spazio dei nomi System.Runtime.CompilerServices. È in CompilerServices perché non è un tipo di dizionario per scopi generici: intendiamo che venga utilizzato solo dagli scrittori di compilatori.

e poi ancora:

... tavolo deboli condizionale non è destinato ad essere una collezione di uso generale ... Ma se si sta scrivendo un linguaggio .NET di proprio e necessità per esporre la capacità di attaccare le proprietà agli oggetti, dovresti assolutamente guardare nella Tabella Debole Condizionale.

In linea con questo, la descrizione ingresso MSDN della classe recita:

Consente compilatori per collegare dinamicamente i campi degli oggetti da oggetti gestiti.

Quindi, ovviamente, è stato originariamente creato per uno scopo molto specifico - per aiutare il DLR, e lo spazio dei nomi System.Runtime.CompilerServices lo rappresenta. Ma sembra aver trovato un uso molto più ampio di quello - anche all'interno del CLR. Se cerco riferimenti di ConditionalWeakTable in ILSpy, ad esempio, posso vedere che viene utilizzato nella classe MEF CatalogExportProvider e nella classe interna WPF DataGridHelper, tra gli altri.

La mia domanda è se sia corretto utilizzare ConditionalWeakTable al di fuori degli strumenti di scrittura e lingua del compilatore e se ci sia qualche rischio in tal senso in termini di costi aggiuntivi o dell'implementazione che cambia in modo significativo nelle future versioni di .NET. (O dovrebbe essere evitato e si dovrebbe usare un'implementazione personalizzata come this one).

C'è anche la lettura ulteriore here, here e here su come il ConditionalWeakTable fa uso di un'implementazione CLR nascosta ephemerons (via System.Runtime.Compiler.Services. DependentHandle) per affrontare il problema di cicli tra chiavi e valori, e come questo non può essere facilmente espletato in modo personalizzato.

risposta

22

Non vedo niente di sbagliato nell'uso di ConditionalWeakTable. Se hai bisogno di effimeri, praticamente non hai altra scelta.

Non penso che le future versioni di .NET saranno un problema - anche se solo i compilatori userebbero questa classe, Microsoft non potrebbe ancora cambiarla senza rompere la compatibilità con i binari esistenti.

Per quanto riguarda il sovraccarico, ci sarà sicuramente un sovraccarico rispetto a un normale dizionario. Avere molti DependentHandle s probabilmente sarà costoso in modo simile al numero di WeakReference s più costosi rispetto ai normali riferimenti (il GC deve fare del lavoro aggiuntivo per scansionarli per vedere se è necessario annullarli). Ma questo non è un problema a meno che tu non abbia molti (diversi milioni) di voci.

+0

Grazie, lo segnerò come risposta. Penso che tu abbia ragione: voglio un dizionario che utilizzi riferimenti deboli, quindi ConditionalWeakTable non dovrebbe introdurre un sovraccarico maggiore rispetto a qualsiasi altra implementazione che utilizza riferimenti deboli, con l'ulteriore vantaggio di utilizzare gli effemeroni. – Riko

+0

Ero davvero entusiasta della disponibilità di ConditionalWeakTable, ma ho notato questo nella documentazione: "Non puoi controllare i confronti di uguaglianza sovrascrivendo Object.GetHashCode per impostare esplicitamente il codice hash per una chiave.La classe ConditionalWeakTable non utilizzare il metodo Object.GetHashCode per calcolare i codici hash e pertanto non richiama le sostituzioni Object.GetHashCode. " - Rendendolo non utile per i miei scopi. :( – ctrlplusb

+6

@Sean: Non c'è un modo in cui "ConditionalWeakTable" potrebbe utilizzare qualcosa di diverso dall'identità di riferimento per le chiavi, poiché sarebbe impossibile (Halting Problem) sapere quando non era più possibile che il codice fornisse una chiave che dovrebbe corrispondere a un elemento nella raccolta. – supercat

Problemi correlati