Stiamo creando alcuni analizzatori di Roslyn riguardanti GetHashCode()
, incluso un analizzatore che lo implementa per te in una determinata classe.
Durante le ricerche sull'argomento abbiamo rilevato che ci sono molte considerazioni da prendere in considerazione, principalmente su quale tipo di membri dovrebbero essere evitati in un'implementazione GetHashCode()
.
Il tipo principale di membri da evitare sono membri mutabili (per evitare le modifiche al codice hash quando vengono utilizzate in una raccolta).
In general, for mutable reference types, you should override
GetHashCode
only if:
- You can compute the hash code from fields that are not mutable
Ora la domanda che rimane: che tipo di membri stiamo parlando allora? Il membro deve essere immutabile, ma anche in questo caso dovrebbe essere (idealmente) diverso per ogni istanza, altrimenti ti ritroverai con lo stesso codice hash per ogni oggetto.
Questo mi porta a concludere che gli unici membri accettabili per un'implementazione GetHashCode()
sono structly immutable structs e classi readonly immutable Nota: not const
. Allo stesso modo, nessun campo static
poiché sarebbero uguali in tutte le istanze comunque.
Il modo in cui questo sarebbe implementato nella realtà sarebbe usando un
- Campo:
readonly T myField
- Proprietà:
T myProp { get; }
Dato che non sarebbe possibile determinare se una classe è immutabile, dovremmo probabilmente eliminarla del tutto a parte forse da string
.
Questo lascia l'elenco dei membri applicabili per un'implementazione GetHashCode()
a:
- Campi di sola lettura
- Proprietà getter-only
- Sono strutture immutabili
- E non sono
static
- E non sono interfacce
- +
string
Sembra corretto o ho fatto un errore nel processo di pensiero da qualche parte? Sembra che all'improvviso ci siano molti meno campi di quelli che le persone normalmente usano. Mi rendo conto che c'è un aspetto pragmatico a questo che dice semplicemente "aggiungi tutti i campi e lascia che sia lo sviluppatore a capirlo", ma cerco di evitare di introdurre bug nascosti negli analizzatori.