CA2218: オーバーライドする Equals で GetHashCode をオーバーライドします
TypeName |
OverrideGetHashCodeOnOverridingEquals |
CheckId |
CA2218 |
[カテゴリ] |
Microsoft.Usage |
互換性に影響する変更点 |
なし |
原因
パブリック型は Object.Equals をオーバーライドしますが、Object.GetHashCode をオーバーライドしません。
規則の説明
GetHashCode は、現在のインスタンスに基づいて、ハッシュ アルゴリズムやデータ構造 (ハッシュ テーブルなど) に適した値を返します。以下の型のインスタンスが適切に機能するには、同じ型で等値の 2 つのオブジェクトによって同じハッシュ コードが返される必要があります。
HashTable
Dictionary
SortDictionary
SortList
HybredDictionary
IEqualityComparer を実装する型
違反の修正方法
この規則違反を修正するには、GetHashCode を実装します。同じ型のオブジェクト ペアの場合、Equals の実装でそのペアに対して true を返すときに、同じ値を返す実装にする必要があります。
警告を抑制する状況
この規則による警告は抑制しないでください。
クラスの例
Description
この規則に違反するクラス (参照型) を次の例に示します。
コード
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;
}
}
}
コメント
GetHashCode をオーバーライドすることによって違反を修正するコード例を次に示します。
コード
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);
}
}
}
構造体の例
Description
この規則に違反する構造体 (値型) の定義を次の例に示します。
コード
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);
}
}
}
コメント
GetHashCode をオーバーライドすることによって違反を修正するコード例を次に示します。
コード
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);
}
}
}
関連規則
CA1046: 参照型で、演算子 equals をオーバーロードしないでください
CA2225: 演算子オーバーロードには名前付けされた代替が存在します
CA2226: 演算子は対称型オーバーロードを含まなければなりません
CA2224: オーバーロードする演算子 equals で Equals をオーバーライドします
CA2231: ValueType.Equals のオーバーライドで、演算子 equals をオーバーロードします
参照
関連項目
Guidelines for Implementing Equals and the Equality Operator (==)
HashTable