Nella mia applicazione ho un metodo di servizio che carica alcuni dati. La chiave che identifica i dati è costituita da un tipo di chiave, definito come enum, e da alcuni valori chiave.
public enum KeyType
{
Alpha,
Bravo,
Charlie
}
public class KeyData
{
public KeyType KeyType { get; set; }
public string AlphaKey { get; set; }
public string BravoKey { get; set; }
public int? CharlieKey { get ;set; }
}
Quali valori chiave sono necessari dipende dal tipo di chiave. Ad esempio per il tipo di chiave Alpha
è necessario solo AlphaKey
mentre per il tipo di chiave Charlie
sono necessari sia BravoKey
che CharlieKey
. Quando si utilizza la chiave per il caricamento, i valori sconosciuti per il tipo di chiave e / oi valori chiave superflui vengono semplicemente ignorati e non viene restituito alcun dato.
Ora voglio memorizzare le chiavi in una raccolta. Nessuna chiave dovrebbe apparire due volte in questa raccolta. Quando si confrontano le chiavi due devono essere considerate uguali quando hanno lo stesso tipo di chiave e anche tutti i valori chiave necessari per quel tipo sono uguali. Per raggiungere questo obiettivo, voglio creare una classe che implementa IEqualityComparer<KeyData>
.
Poiché è menzionato su MSDN che sostituisce GetHashCode
non dovrei buttarlo L'ho preso per la mia classe e implementato in questo modo:
public class KeyDataComparer : IEqualityComparer<KeyData>
{
public int GetHashCode(KeyData obj)
{
if (obj == null)
return 0;
unchecked
{
int hash = 17;
switch (obj.KeyType)
{
case KeyType.Alpha:
hash = hash * 486187739 + obj.AlphaKey?.GetHashCode() ?? 0;
break;
case KeyType.Bravo:
hash = hash * 486187739 + obj.BravoKey?.GetHashCode() ?? 0;
break;
case KeyType.Charlie:
hash = hash * 486187739 + obj.BravoKey?.GetHashCode() ?? 0;
hash = hash * 486187739 + obj.CharlieKey?.GetHashCode() ?? 0;
break;
default:
// use object.GetHashCode() as a fallback
hash = obj?.GetHashCode() ?? 0;
break;
}
return hash;
}
Il problema ora è come gestire tipi di chiavi non validi in IEqualityComparer<T>.Equals
? L'ho fatto così:
public bool Equals(KeyData x, KeyData y)
{
if (x == null)
return y == null;
if (x.KeyType != y.KeyType)
return false;
switch (x.KeyType)
{
case KeyType.Alpha:
return x.AlphaKey == y.AlphaKey;
case KeyType.Bravo:
return x.BravoKey == y.BravoKey;
case KeyType.Charlie:
return x.BravoKey == y.BravoKey &&
x.CharlieKey == y.CharlieKey;
default:
throw new InvalidOperationException();
}
}
Ma questo non sembra corretto perché è un comportamento incoerente. C'è un modo significativo per avere Equals
e GetHashCode
comportarsi in modo coerente?