CA2218: オーバーライドする Equals で GetHashCode をオーバーライドします

TypeName

OverrideGetHashCodeOnOverridingEquals

CheckId

CA2218

カテゴリ

Microsoft.Usage

互換性に影響する変更点

なし

原因

パブリック型は Object.Equals をオーバーライドしますが、Object.GetHashCode をオーバーライドしません。

規則の説明

GetHashCode は、現在のインスタンスに基づいて、ハッシュ アルゴリズムやデータ構造 (ハッシュ テーブルなど) に適した値を返します。 以下の型のインスタンスが適切に機能するには、同じ型で等値の 2 つのオブジェクトによって同じハッシュ コードが返される必要があります。

違反の修正方法

この規則違反を修正するには、GetHashCode を実装します。 同じ型のオブジェクト ペアの場合、Equals の実装でそのペアに対して true を返すときに、同じ値を返す実装にする必要があります。

警告を抑制する状況

この規則による警告は抑制しないでください。

クラスの例

説明

この規則に違反するクラス (参照型) を次の例に示します。

コード

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);        
        }    
    }
}

構造体の例

説明

この規則に違反する構造体 (値型) の定義を次の例に示します。

コード

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 をオーバーロードします

参照

参照

Equals および等値演算子 (==) 実装のガイドライン

Object.Equals

Object.GetHashCode

HashTable