2009-10-30 12 views
9

Ho un dizionario che sto confrontando con un altro dizionario (variabili digitate come IDictionary). Fare d1.Equals (d2) produce false. Scrivendo il mio codice qui sotto si ottiene vero. Entrambi sono System.Collections.Generic.Dictionary. Mi manca qualcosa o Dictionary non ha un'implementazione Equals che confronta chiavi/valori?Does Dictionary.Equals() ha un'implementazione?

private static bool DictEquals<K, V>(IDictionary<K, V> d1, IDictionary<K, V> d2) 
{ 
    if (d1.Count != d2.Count) 
     return false; 

    foreach (KeyValuePair<K, V> pair in d1) 
    { 
     if (!d2.ContainsKey(pair.Key)) 
      return false; 

     if (!Equals(d2[pair.Key], pair.Value)) 
      return false; 
    } 

    return true; 
} 

risposta

10

Dictionary.Equals() utilizza il valore predefinito Equals from Object, controllando se i due oggetti sono lo stesso riferimento, come tutte le altre raccolte predefinite. Sei libero di creare la tua sottoclasse con la semantica del valore, sebbene di solito includa anche cose immutabili.

+2

+1, come indicato nella documentazione della classe del dizionario. http://msdn.microsoft.com/en-us/library/3eayzh46.aspx. –

5

Probabilmente il metodo della classe DictionaryEquals ricorre semplicemente per l'implementazione predefinita ereditata da Object, cioè, solo a confronto il riferimento Dictionary oggetto passato con il proprio riferimento. Vedi qui: Object.Equals reference

1

Altri hanno detto che si sta usando l'attuazione Object.Equals, è possibile utilizzare il seguente per ignorare che:

public class EqualsDictionary<T, T> : Dictionary<T, T> 
{ 
    public override bool Equals(object obj) 
    { 
     //Place your comparison implementation here 
    } 
} 
+2

Per * sostituirlo *, come dice la parola chiave. Il sovraccarico è qualcosa di diverso. – Joren

+0

@Joren: Sì, ancora troppo presto per me. –

2

Supponendo che due dizionari, uno è un SortedList<TKey, TValue> e uno un Dictionary<TKey, TValue>, vengono confrontati per uguaglianza, dovrebbe davvero tornare vero se gli articoli sono gli stessi? Sarebbe piuttosto brutto, dato che hanno caratteristiche e caratteristiche diverse (per esempio lo SortedList<,> consente il recupero tramite indice).

Inoltre, l'uguaglianza e il codice hash sono logicamente legati insieme. Il codice hash dovrebbe essere immutabile, altrimenti tutti gli algoritmi basati su hash non funzioneranno. Non puoi garantire questo quando stai usando i contenuti per verificare l'uguaglianza. Pertanto, l'implementazione di default (controllando se sono la stessa istanza) è abbastanza sana. Sei libero di creare il tuo confronto sull'uguaglianza dei contenuti.

+0

Punto giusto, il mio codice sopra dovrebbe fare la solita verifica della comparabilità identity + class prima di confrontare il contenuto. –

+0

Giusto. Tuttavia, questo non sarebbe ancora un sostituto adatto per Equals() a causa del problema di hashcode: se due oggetti sono uguali il loro hashcode deve essere uguale, e il codice hash deve essere immutabile. Di conseguenza, Equals() potrebbe non restituire true solo perché due insiemi sono dello stesso tipo con gli stessi contenuti, perché avranno ancora un hashcode diverso (immutabile, mi dispiace enfatizzarlo). – Lucero

+0

@Lucero: Peccato.NET definisce solo un insieme di metodi di relazione di equivalenza virtuale, dal momento che molti tipi di classi "immutabili" contengono riferimenti a oggetti che potrebbero essere mutevoli * eccetto che i riferimenti non saranno mai esposti a qualcosa che potrebbe mutarli * e sarebbe utile se erano metodi standard che quelle classi di wrapper immutabili potevano usare per hash o controllare l'uguaglianza sui loro contenuti. – supercat

0

I riferimenti in .NET possono essere utilizzati per incapsulare l'identità di un oggetto, aspetti mutabili del suo stato, entrambi o nessuno dei due, oltre all'incapsulamento di aspetti immutabili dello stato di un oggetto. In generale, in assenza di una ragione particolare per assumere il contrario, .NET presuppone che i riferimenti a oggetti mutabili siano utilizzati allo scopo di incapsulare l'identità. Suppone inoltre che nei casi in cui il codice sta confrontando i riferimenti senza sapere cosa rappresentano, è meglio sbagliare dalla parte della segnalazione di cose non uguali. In quanto tali, due riferimenti a oggetti mutabili sono generalmente considerati equivalenti se e solo se identificano lo stesso oggetto, e i tipi mutabili sono quindi scoraggiati dall'override Equals per indicare qualcos'altro. Invece, il codice che utilizza i riferimenti per incapsulare lo stato mutabile dovrebbe utilizzare mezzi diversi da Object.Equals() per confrontarli.

Problemi correlati