2015-02-11 9 views
15

Ho due clienti che creano IPAddress casi dalla stessa byte[] e inviarlo al server tramite WCF (usando DataContractSerializer).due uguali casi IPv6 IndirizzoIP ritorno diverso GetHashCode risultati

Sul server, queste istanze IPAddress vengono inserite come chiavi in ​​un dizionario ma per qualche motivo vengono aggiunte come chiavi diverse.

Durante la registrazione, vedo che sono uguali ma GetHashCode restituisce risultati diversi.

var client1Address = // sent from client1 
var client2Address = // sent from client2 

Console.WriteLine(client1Address.Equals(client2Address)); 
Console.WriteLine(client1Address.GetHashCode().Equals(client2Address.GetHashCode())); 

uscita:

true 
false 

Come può essere uguale IPAddress casi restituiscono diversi GetHashCode risultati?

risposta

16

La GetHashCode implementation di IPAddress per IPv6 è:

if (m_HashCode == 0) 
{ 
    m_HashCode = StringComparer.InvariantCultureIgnoreCase.GetHashCode(ToString()); 
    return m_HashCode; 
} 

Per evitare ricalcolare nuovamente il codice hash e ancora una volta, stanno memorizzando il risultato in un membro privato. Questo membro privato viene quindi serializzato sul server remoto.

Il fatto è che StringComparer.InvariantCultureIgnoreCase.GetHashCode(ToString()) restituisce risultati diversi su diverse versioni del sistema operativo e poiché m_HashCode è serializzato, il server non lo ricalcola.

Ciò comporta due istanze identiche IPAddress con risultati diversi GetHashCode.

Penso che il membro privato m_HashCode debba essere contrassegnato come [NonSerialized], che causerà GetHashCode per rigenerare il codice hash localmente e correttamente.

Come soluzione temporanea, ho interferito nel processo di serializzazione e serializzato come byte[].


Here's the bug on VisualStudio connect. Questo collegamento è morto in quanto il bug è stato chiuso per questi motivi:

"Grazie per aver segnalato questo problema. Purtroppo, il nostro team non è in grado di risolvere questo problema a causa di altri elementi con priorità più alta. al contenuto serializzato di un tipo si rischia di rompere app che hanno preso una dipendenza da tale comportamento. "

+2

Scoperta interessante. – Lloyd

+0

Credo che questo scenario esatto sia avvertito in .NET GetHashCode e String Compare e gli operatori di Equality basati su stringhe. Non penso che questo sia un bug in quanto GetHashCode è effettivamente una proprietà di runtime .NET privata che non dovrebbe essere utilizzata direttamente dal nostro codice a livello di applicazione. Dato che IPV6 è una cosa nota, utilizzerei l'indirizzo stesso come codice Hash o operatore di uguaglianza. Ma vorrei fare il confronto reale a livello di byte per un valore formattato. Simile a come funziona guid. "ABCD-123" = "abcd123" Da una prospettiva di progettazione penso che sia un bug. Possono cambiarlo ora? –

+4

@SqlSurfer 'GetHashCode' non è privato e non viene utilizzato direttamente. Quando usi 'IPAddress' come chiave di dizionario usa internamente 'GetHashCode'. Il bug qui è che il codice hash è memorizzato nella cache e serializzato quando non dovrebbe essere. – i3arnon