Eseguire l'override di GetHashCode all'override di Equals
Aggiornamento: novembre 2007
TypeName |
OverrideGetHashCodeOnOverridingEquals |
CheckId |
CA2218 |
Category |
Microsoft.Usage |
Breaking Change |
Non sostanziale |
Causa
Un tipo pubblico esegue l'override di Object.Equals, ma non di Object.GetHashCode.
Descrizione della regola
Il metodo GetHashCode restituisce un valore, basato sull'istanza corrente, appropriato per algoritmi di hash e strutture di dati come una tabella hash. Due oggetti dello stesso tipo e uguali devono restituire lo stesso codice hash per assicurare il corretto funzionamento delle istanze dei tipi seguenti:
HashTable
Dictionary
SortDictionary
SortList
HybredDictionary
Tipi che implementano IEqualityComparer
Correzione di violazioni
Per correggere una violazione di questa regola, fornire un'implementazione di GetHashCode. Per una coppia di oggetti dello stesso tipo, è necessario assicurarsi che l'implementazione restituisca lo stesso valore se implementazione di Equals restituisce true per la coppia.
Esclusione di avvisi
Non escludere un avviso da questa regola.
Esempio di classe
Descrizione
Nell'esempio riportato di seguito viene illustrata una classe (tipo di riferimento) che viola questa regola.
Codice
using System;
namespace Samples
{
// Violates this rule
public class Point
{
private readonly int _X;
private readonly int _Y;
public Point(int x, int y)
{
_X = x;
_Y = y;
}
public int X
{
get { return _X; }
}
public int Y
{
get { return _Y; }
}
public override bool Equals(object obj)
{
if (obj == null)
return false;
if (GetType() != obj.GetType())
return false;
Point point = (Point)obj;
if (_X != point.X)
return false;
return _Y == point.Y;
}
}
}
Commenti
Nell'esempio seguente viene corretta la violazione eseguendo l'override di GetHashCode.
Codice
using System;
namespace Samples
{
public struct Point : IEquatable<Point>
{
private readonly int _X;
private readonly int _Y;
public Point(int x, int y)
{
_X = x;
_Y = y;
}
public int X
{
get { return _X; }
}
public int Y
{
get { return _Y; }
}
public override int GetHashCode()
{
return _X ^ _Y;
}
public override bool Equals(object obj)
{
if (!(obj is Point))
return false;
return Equals((Point)obj);
}
public bool Equals(Point other)
{
if (_X != other._X)
return false;
return _Y == other._Y;
}
public static bool operator ==(Point point1, Point point2)
{
return point1.Equals(point2);
}
public static bool operator !=(Point point1, Point point2)
{
return !point1.Equals(point2);
}
}
}
Esempio di struttura
Descrizione
Nell'esempio riportato di seguito viene mostrata una struttura (tipo di valore) che viola questa regola.
Codice
using System;
namespace Samples
{
// Violates this rule
public struct Point : IEquatable<Point>
{
private readonly int _X;
private readonly int _Y;
public Point(int x, int y)
{
_X = x;
_Y = y;
}
public int X
{
get { return _X; }
}
public int Y
{
get { return _Y; }
}
public override bool Equals(object obj)
{
if (!(obj is Point))
return false;
return Equals((Point)obj);
}
public bool Equals(Point other)
{
if (_X != other._X)
return false;
return _Y == other._Y;
}
public static bool operator ==(Point point1, Point point2)
{
return point1.Equals(point2);
}
public static bool operator !=(Point point1, Point point2)
{
return !point1.Equals(point2);
}
}
}
Commenti
Nell'esempio seguente viene corretta la violazione eseguendo l'override di GetHashCode.
Codice
using System;
namespace Samples
{
public struct Point : IEquatable<Point>
{
private readonly int _X;
private readonly int _Y;
public Point(int x, int y)
{
_X = x;
_Y = y;
}
public int X
{
get { return _X; }
}
public int Y
{
get { return _Y; }
}
public override int GetHashCode()
{
return _X ^ _Y;
}
public override bool Equals(object obj)
{
if (!(obj is Point))
return false;
return Equals((Point)obj);
}
public bool Equals(Point other)
{
if (_X != other._X)
return false;
return _Y == other._Y;
}
public static bool operator ==(Point point1, Point point2)
{
return point1.Equals(point2);
}
public static bool operator !=(Point point1, Point point2)
{
return !point1.Equals(point2);
}
}
}
Regole correlate
Non eseguire l'overload dell'operatore "uguale a" per i tipi di riferimento
Gli overload degli operatori hanno alternative con nome
Gli operatori devono avere overload simmetrici
Eseguire l'override di Equals all'overload dell'operatore "uguale a"
Eseguire l'overload dell'operatore "uguale a" all'override di ValueType.Equals
Vedere anche
Riferimenti
Linee guida per l'implementazione del metodo Equals e dell'operatore di uguaglianza (==)
HashTable