Поделиться через


CA2218: переопределяйте GetHashCode при переопределении Equals

TypeName

OverrideGetHashCodeOnOverridingEquals

CheckId

CA2218

Категория

Microsoft.Usage

Критическое изменение

Не критическое

Причина

Открытый тип переопределяет Object.Equals, но не переопределяет Object.GetHashCode.

Описание правила

GetHashCode возвращает значение на основе текущего экземпляра, используемое для алгоритмов хэширования и структур данных, таких как таблица хэша.Два равных друг другу объекта одинакового типа должны возвращать одинаковый код хэша, чтобы экземпляры следующих типов правильно работали:

Устранение нарушений

Чтобы устранить нарушение данного правила, предоставьте реализацию 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: не перегружайте оператор равенства для ссылочных типов

CA2225: для перезагрузок оператора существуют дополнения с именами

CA2226: перегрузки операторов должны быть симметричны

CA2224: переопределяйте равенство при перегрузке оператора равенства

CA2231: перегружать равенство операторов следует при перегрузке ValueType.Equals

См. также

Ссылки

Object.Equals

Object.GetHashCode

HashTable

Другие ресурсы

Guidelines for Implementing Equals and the Equality Operator (==)