CA2224: Eşittir işlecini aşırı yükleyerek eşittiri geçersiz kılın

TürAdı

OverrideEqualsOnOverloadingOperatorEquals

CheckId

CA2224

Kategori

Microsoft.Usage

Bozan Değişiklik

Bozmayan

Sebep

Ortak bir tür, eşitlik işlecini uygular; ancak Object.Equals'ı geçersiz kılmaz.

Kural Tanımı

Eşitlik işleci, Equals yönteminin işlevselliğine erişmek için sözdizimi kurallarına uygun bir yol amaçlamıştır.Eğer eşitlik işlecini uygularsanız, kendi mantığı Equals özdeş olmalıdır.

Eğer kodunuz bu kuralı bozuyorsa; C# derleyicisi bir uyarı verir.

İhlallerin Düzeltilmesi

Bu kuralın ihlalini düzeltmek için, eşitlik işlecinin uygulamasını kaldırın veya Equals 'ı geçersiz kılın ve aynı değeri döndüren iki yönteme sahip olun.Eğer eşitlik işleci tutarsız davranış sunarsa; temel sınıfta Equals yöntemini çağıran bir Equals uygulamasını sağlayarak bu kuralın ihlalini düzeltebilirsiniz.

Uyarılar Ne Zaman Bastırılmalı

Eğer eşitlik işleci Equals uygulamasından devralanla aynı değeri döndürüyorsa; bu kuraldan bir uyarısının bastırılması güvenlidir.Örnek bölüm, bu kuraldan bir uyarıyı güvenle bastıran bir türü içerir.

Tutarsız Eşitlik Tanımları örnekleri

Description

Aşağıdaki örnek, eşitliğin tutarsız tanımları ile bir türü gösterir.BadPoint eşitlik işlecinin özel bir uygulamasını sağlayarak eşitliğin anlamını değiştirir; ancak Equals 'ı bastıramaz böylece özdeş olarak davranır.

Kod

using System;

namespace UsageLibrary
{   
    public class BadPoint
    {
        private int x,y, id;
        private static int NextId;

        static BadPoint()
        {
            NextId = -1;
        }
        public BadPoint(int x, int y)
        {
            this.x = x;
            this.y = y;
            id = ++(BadPoint.NextId); 
        }

        public override string ToString()
        {
            return String.Format("([{0}] {1},{2})",id,x,y);
        }

        public int X {get {return x;}}

        public int Y {get {return x;}}
        public int Id {get {return id;}}

        public override int GetHashCode()
        {
            return id;
        }
        // Violates rule: OverrideEqualsOnOverridingOperatorEquals. 

        // BadPoint redefines the equality operator to ignore the id value. 
        // This is different from how the inherited implementation of  
        // System.Object.Equals behaves for value types.  
        // It is not safe to exclude the violation for this type.  
        public static bool operator== (BadPoint p1, BadPoint p2)
        {
            return ((p1.x == p2.x) && (p1.y == p2.y));
        }
        // The C# compiler and rule OperatorsShouldHaveSymmetricalOverloads require this. 
        public static bool operator!= (BadPoint p1, BadPoint p2)
        {
            return !(p1 == p2);
        }
    }
}

Örnek

Aşağıdaki kod BadPoint'in davranışını sınar.

using System;

namespace UsageLibrary
{   
    public class TestBadPoint
    {
        public static void Main()
        {
            BadPoint a = new BadPoint(1,1);
            BadPoint b = new BadPoint(2,2);
            BadPoint a1 = a;
            BadPoint bcopy = new BadPoint(2,2);

            Console.WriteLine("a =  {0} and b = {1} are equal? {2}", a, b, a.Equals(b)? "Yes":"No");
            Console.WriteLine("a == b ? {0}", a == b ? "Yes":"No");
            Console.WriteLine("a1 and a are equal? {0}", a1.Equals(a)? "Yes":"No");
            Console.WriteLine("a1 == a ? {0}", a1 == a ? "Yes":"No");

            // This test demonstrates the inconsistent behavior of == and Object.Equals.
            Console.WriteLine("b and bcopy are equal ? {0}", bcopy.Equals(b)? "Yes":"No");
            Console.WriteLine("b == bcopy ? {0}", b == bcopy ? "Yes":"No");
        }
    }
}

Bu örnek aşağıdaki çıktıyı üretir.

  
  
  
  
  
  
  

Aşağıdaki örnek, teknik açıdan bu kuralı ihlal eden bir türü gösterir; ancak tutarsız bir şekilde davranmasına davranmaz.

using System;

namespace UsageLibrary
{
    public struct GoodPoint
    {
        private int x,y;

        public GoodPoint(int x, int y)
        {
            this.x = x;
            this.y = y;
        }

        public override string ToString()
        {
            return String.Format("({0},{1})",x,y);
        }

        public int X {get {return x;}}

        public int Y {get {return x;}}

        // Violates rule: OverrideEqualsOnOverridingOperatorEquals, 
        // but does not change the meaning of equality; 
        //  the violation can be excluded. 

        public static bool operator== (GoodPoint px, GoodPoint py)
        {
            return px.Equals(py);
        }

        // The C# compiler and rule OperatorsShouldHaveSymmetricalOverloads require this. 
        public static bool operator!= (GoodPoint px, GoodPoint py)
        {
            return !(px.Equals(py));
        }
    }
}

Aşağıdaki kod GoodPoint'in davranışını sınar.

using System;

namespace UsageLibrary
{ 
    public class TestGoodPoint
    {
        public static void Main()
        {
            GoodPoint a = new GoodPoint(1,1);
            GoodPoint b = new GoodPoint(2,2);
            GoodPoint a1 = a;
            GoodPoint bcopy = new GoodPoint(2,2);

            Console.WriteLine("a =  {0} and b = {1} are equal? {2}", a, b, a.Equals(b)? "Yes":"No");
            Console.WriteLine("a == b ? {0}", a == b ? "Yes":"No");
            Console.WriteLine("a1 and a are equal? {0}", a1.Equals(a)? "Yes":"No");
            Console.WriteLine("a1 == a ? {0}", a1 == a ? "Yes":"No");

            // This test demonstrates the consistent behavior of == and Object.Equals.
            Console.WriteLine("b and bcopy are equal ? {0}", bcopy.Equals(b)? "Yes":"No");
            Console.WriteLine("b == bcopy ? {0}", b == bcopy ? "Yes":"No");
        }
    }
}

Bu örnek aşağıdaki çıktıyı üretir.

  
  
  
  
  
  
  

Aşağıdaki örnek Object.Equals geçersiz kılarak ihlali giderir.

using System; 

namespace Samples
{    
    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 int GetHashCode()        
        {            
            return _X ^ _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;        
        }         

        public static bool operator ==(Point point1, Point point2)        
        {            
            return Object.Equals(point1, point2);        
        }         

        public static bool operator !=(Point point1, Point point2)        
        {            
            return !Object.Equals(point1, point2);        
        }    
    }
}

Aşağıdaki örnek ValueType.Equals geçersiz kılarak ihlali giderir.

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

Sınıf Örneği

Description

Aşağıdaki örnek, bu kuralı ihlal eden bir sınıfı (başvuru türü) gösterir.

Kod

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 int GetHashCode()        
        {            
            return _X ^ _Y;        
        }             

        public static bool operator ==(Point point1, Point point2)        
        {            
            if (point1 == null || point2 == null)                
                return false;             

            if (point1.GetType() != point2.GetType())                
                return false;             

            if (point1._X != point2._X)                    
                return false;             

            return point1._Y == point2._Y;        
        }         

        public static bool operator !=(Point point1, Point point2)        
        {            
            return !(point1 == point2);        
        }    
    }
}

Yapı Örneği

Description

Aşağıdaki örnek, bu kuralı ihlal eden bir yapıyı (değer türü) gösterir.

Kod

using System; 

namespace Samples
{    
    // Violates this rule     
    public struct 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 static bool operator ==(Point point1, Point point2)        
        {            
            if (point1._X != point2._X)                
                return false;                        

            return point1._Y == point2._Y;        
        }         

        public static bool operator !=(Point point1, Point point2)        
        {            
            return !(point1 == point2);        
        }    
    }
}

İlgili Kurallar

CA1046: Başvuru türlerinde eşittir işleçlerini aşırı yüklemeyin

CA2225: İşleç aşırı yüklemeleri adlandırılmış alternatiflere sahiptir

CA2226: İşleçler simetrik aşırı yüklemelere sahip olmalıdır

CA2218: GetHashCode'u Eşittir'i geçersiz kılarak geçersiz kılın

CA2231: ValueType.Equals değerini geçersiz kılmada eşittir işlecini aşırı yükle