2013-04-23 7 views
7

Se si dispone dell'oggetto Dictionary<k, v> myDictionary, quindi myDictionary.Values sarà di tipo Dictionary<k, v>.ValueCollection e myDictionary.Keys sarà di tipo Dictionary<k, v>.KeyCollection.Quale tipo deve restituire myCustomDictionary.Values?

Non capisco perché il tipo di myDictionary.Values non sia qualcosa come IEnumerable<v>, IList<v> o altro.

Ora, con questo in mente, se creo un tipo personalizzato di dizionario; Dictionary2<k1, k2, v>, myCustomDictionary.Values restituisce un IEnumerable<v> o uno strumento personalizzato di ValueCollection? Ancora più importante, perché?

+2

Domanda molto interessante :) –

risposta

5

noti che Dictionary<TKey, TValue>.ValueCollection fa infatti attuare ICollection<TValue> e quindi anche IEnumerable<TValue>.

Il motivo per cui la proprietà è digitato il modo in cui è è probabile che per motivi di prestazioni: dal momento che i metodi di questa classe non sono virtuali, possono essere esattamente risolti durante la compilazione JIT, invece di richiedere ricerche vtable per ogni metodo chiamata al runtime. Ciò rimuove efficacemente un livello di riferimento indiretto da ogni metodo che chiamate sulla raccolta. (Dà anche alla JIT la possibilità di inlineare quelle chiamate di metodo!)

Ovviamente, è possibile convertire implicitamente l'oggetto in ICollection<TValue> se necessario, quindi non c'è alcuna perdita di funzionalità qui, solo un po 'di (micro) ottimizzazione .

Nel tuo caso, non v'è alcuna ragione per cui non si può tornare ICollection<TValue>, ma si può restituire un tipo più specifico se si desidera. Se lo fai, allora si dovrà implementare in modo esplicito la proprietà di interfaccia IDictionary<TKey, TValue>.Values per soddisfare l'interfaccia:

private ValueCollection valueCollection; 

public ValueCollection Values 
{ 
    get { return valueCollection; } 
} 

ICollection<TValue> IDictionary<TKey, TValue>.Values 
{ 
    get { return valueCollection; } 
} 

Ciò implica correttamente che qualsiasi miglioramento delle prestazioni sarà dato solo ai consumatori della classe se si utilizza un riferimento digitato come tipo di raccolta; non ci sarà alcun vantaggio in termini di prestazioni se prenderanno un riferimento a IDictionary<TKey, TValue>, in quanto dovranno scegliere comunque di accedere alla propria collezione di valori tramite ICollection<TValue>.

Nel mio lavoro, non ho trovato la differenza di prestazioni sufficientemente significativa da giustificare la restituzione di qualcosa di più specifico di ICollection<TValue>. Ricorda: sempre punto di riferimento, e mai prematuramente ottimizzare.

+1

Cosa, questa risposta contiene molte informazioni. Grazie mille signore! – Tipx

+0

'Elenco ' e 'Dizionario ' sono le implementazioni più utilizzate di 'IList ' e 'IDictionary '. Pertanto, la prevenzione delle chiamate di dispacciamento dell'interfaccia non necessarie ha un effetto aggregato sull'intero ecosistema .NET e contribuisce a un vantaggio energetico del dispositivo mobile che Java non sarà mai in grado di toccare (a causa dell'uso eccessivo di metodi sovrascrivibili nelle classi dell'infrastruttura). –

1

Dictionary<k, v>.ValueCollection implementa IEnumerable<v> e Dictionary<k, v>.KeyCollection attrezzi IEnumerable<k>. Non è come se i risultati che vengono restituiti non siano enumerabili.

Restituendo una classe effettiva che implementa IEnumerable anziché immettere il risultato come IEnumerable, è possibile includere anche alcune funzionalità aggiuntive. Ad esempio, entrambe le raccolte hanno una proprietà Count, che non è facilmente accessibile da qualsiasi IEnumerable.

+2

Si noti che 'ICollection ' ha una proprietà Count e 'IDictionary .Values' restituisce un' ICollection '. Quindi * qualsiasi * implementazione di 'IDictionary '* deve * restituire un oggetto' Values' che supporti comunque la proprietà 'Count'. Il tipo più specifico di 'Dictionary .Values' non fornisce in alcun modo funzionalità extra che io possa vedere. – cdhowie

Problemi correlati