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


CA1013: перегружайте оператор равенства при перегрузке сложения и вычитания

TypeName

OverloadOperatorEqualsOnOverloadingAddAndSubtract

CheckId

CA1013

Категория

Microsoft.Design

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

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

Причина

Открытый или защищенный тип реализует операторы сложения или вычитания без реализации оператора равенства.

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

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

Заданный по умолчанию оператор равенства нельзя использовать в перегруженной реализации оператора равенства.Это может привести к переполнению стека.Для реализации оператора равенства воспользуйтесь методом Object.Equals.См. следующий пример.

If (Object.ReferenceEquals(left, Nothing)) Then
    Return Object.ReferenceEquals(right, Nothing)
Else
    Return left.Equals(right)
End If
if (Object.ReferenceEquals(left, null)) 
    return Object.ReferenceEquals(right, null);
return left.Equals(right);

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

Чтобы исправить нарушение этого правила, реализуйте оператор равенства, чтобы он был математически однородным с операторами сложения и вычитания.

Отключение предупреждений

Можно безопасно отключать предупреждения этого правила, если заданная по умолчанию реализация оператора равенства обеспечивает его правильную работу для заданного типа.

Пример

В следующем примере определяется тип (BadAddableType), нарушающий это правило.Этот тип должен реализовать оператор равенства, чтобы любые два экземпляра с одинаковыми значениями полей выдавали значение true для равенства.Тип GoodAddableType демонстрирует исправленную реализацию.Обратите внимание, что этот тип также реализует оператор неравенства и переопределяет Equals для выполнения других правил.При полной реализации также потребуется реализовать GetHashCode.

using System;

namespace DesignLibrary
{
   public class BadAddableType
   {
      private int a, b;
      public BadAddableType(int a, int b)
      {
         this.a = a;
         this.b = b;
      }
      // Violates rule: OverrideOperatorEqualsOnOverridingAddAndSubtract. 
      public static BadAddableType operator +(BadAddableType a, BadAddableType b)
      {
         return new BadAddableType(a.a + b.a, a.b + b.b);
      }
      // Violates rule: OverrideOperatorEqualsOnOverridingAddAndSubtract. 
      public static BadAddableType operator -(BadAddableType a, BadAddableType b)
      {
         return new BadAddableType(a.a - b.a, a.b - b.b);
      }
      public override string ToString()
      {
         return String.Format("{{{0},{1}}}", a, b);
      }
   }

   public class GoodAddableType
   {
      private int a, b;
      public GoodAddableType(int a, int b)
      {
         this.a = a;
         this.b = b;
      }
      // Satisfies rule: OverrideOperatorEqualsOnOverridingAddAndSubtract. 
      public static bool operator ==(GoodAddableType a, GoodAddableType b)
      {
         return (a.a == b.a && a.b == b.b);
      }

      // If you implement ==, you must implement !=. 
      public static bool operator !=(GoodAddableType a, GoodAddableType b)
      {
         return !(a==b);
      }

      // Equals should be consistent with operator ==. 
      public override bool Equals(Object obj)
      {
         GoodAddableType good = obj as GoodAddableType;
         if (obj == null)
            return false;

        return this == good;
      }

      public static GoodAddableType operator +(GoodAddableType a, GoodAddableType b)
      {
         return new GoodAddableType(a.a + b.a, a.b + b.b);
      }

      public static GoodAddableType operator -(GoodAddableType a, GoodAddableType b)
      {
         return new GoodAddableType(a.a - b.a, a.b - b.b);
      }
      public override string ToString()
      {
         return String.Format("{{{0},{1}}}", a, b);
      }
   }
}

В следующем примере проверяется равенство с помощью экземпляров типов, которые были определены раннее в этом разделе, для демонстрации правильного поведения оператора равенства.

using System;

namespace DesignLibrary
{
    public class TestAddableTypes
    {
       public static void Main()
       {
          BadAddableType a = new BadAddableType(2,2);
          BadAddableType b = new BadAddableType(2,2);
          BadAddableType x = new BadAddableType(9,9);
          GoodAddableType c = new GoodAddableType(3,3);
          GoodAddableType d = new GoodAddableType(3,3);
          GoodAddableType y = new GoodAddableType(9,9);

          Console.WriteLine("Bad type:  {0} {1} are equal? {2}", a,b, a.Equals(b)? "Yes":"No");
          Console.WriteLine("Good type: {0} {1} are equal? {2}", c,d, c.Equals(d)? "Yes":"No");
          Console.WriteLine("Good type: {0} {1} are == ?   {2}", c,d, c==d? "Yes":"No");
          Console.WriteLine("Bad type:  {0} {1} are equal? {2}", a,x, a.Equals(x)? "Yes":"No");
          Console.WriteLine("Good type: {0} {1} are == ?   {2}", c,y, c==y? "Yes":"No");
       }
    }
}

В результате выполнения примера получается следующий результат:

           

См. также

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

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