Condividi tramite


CA1013: Eseguire l'overload dell'operatore "uguale a" all'overload degli operatori di addizione e sottrazione

TypeName

OverloadOperatorEqualsOnOverloadingAddAndSubtract

CheckId

CA1013

Category

Microsoft.Design

Breaking Change

Non sostanziale

Causa

Un membro pubblico o protetto implementa gli operatori di addizione o sottrazione senza implementare l'operatore di uguaglianza.

Descrizione della regola

Se le istanze di un tipo possono essere combinate utilizzando operazioni quali l'addizione e la sottrazione è quasi sempre necessario definire l'uguaglianza in modo che restituisca true per due istanze aventi gli stessi valori costitutivi.

Non è possibile utilizzare l'operatore di uguaglianza predefinito in un'implementazione di overload dell'operatore di uguaglianza. Questa operazione causerebbe un overflow dello stack. Per implementare l'operatore di uguaglianza, utilizzare il metodo Object.Equals nell'implementazione. Vedere l'esempio che segue.

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

Come correggere le violazioni

Per correggere una violazione di questa regola, implementare l'operatore di uguaglianza affinché sia matematicamente coerente con gli operatori di addizione e sottrazione.

Esclusione di avvisi

L'esclusione di un avviso da questa regola è sicura quando l'implementazione predefinita dell'operatore di uguaglianza fornisce il comportamento corretto per il tipo.

Esempio

Nell'esempio riportato di seguito viene definito un tipo (BadAddableType) che viola questa regola. Questo tipo deve implementare l'operatore di uguaglianza per fare sì che in caso due istanze presentino gli stessi valori di campo restituiscano true per l'uguaglianza. Il tipo GoodAddableType presenta l'implementazione corretta. Si noti che questo tipo implementa anche l'operatore di disuguaglianza ed esegue l'override di Equals per soddisfare le altre regole. Un'implementazione completa prevede anche l'implementazione di 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);
      }
   }
}

Nell'esempio riportato di seguito viene testata l'uguaglianza utilizzando istanze dei tipi definiti in precedenza in questo argomento per illustrare il comportamento predefinito e il comportamento corretto dell'operatore di uguaglianza.

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

Questo esempio produce l'output che segue.

              

Vedere anche

Riferimenti

Linee guida per l'implementazione del metodo Equals e dell'operatore di uguaglianza (==)