Partager via


Surchargez l'opérateur égal lors de la surcharge de l'opérateur d'addition et de soustraction

Mise à jour : novembre 2007

TypeName

OverloadOperatorEqualsOnOverloadingAddAndSubtract

CheckId

CA1013

Catégorie

Microsoft.CSharp

Modification avec rupture

Modification sans rupture

Cause

Un type public ou protégé implémente les opérateurs d'addition ou de soustraction sans implémenter l'opérateur d'égalité.

Description de la règle

Lorsque des instances d'un type peuvent être combinées à l'aide d'opérations telles que l'addition et la soustraction, vous devez presque systématiquement définir l'égalité de sorte qu'elle retourne une valeur true pour toute paire d'instances affichant les mêmes valeurs constituantes.

Vous ne pouvez pas utiliser l'opérateur d'égalité par défaut dans une implémentation surchargée de l'opérateur d'égalité. Ce procédé provoque un dépassement de capacité de la pile. Pour implémenter l'opérateur d'égalité, utilisez la méthode Object.Equals dans votre implémentation. Par exemple :

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

Comment corriger les violations

Pour corriger une violation de cette règle, implémentez l'opérateur d'égalité afin qu'il soit mathématiquement cohérent avec les opérateurs d'addition et de soustraction.

Quand supprimer les avertissements

Il est possible de supprimer sans risque un avertissement de cette règle lorsque l'implémentation par défaut de l'opérateur d'égalité fournit le comportement correct pour le type.

Exemple

L'exemple suivant définit un type qui enfreint cette règle (BadAddableType). Ce type doit implémenter l'opérateur d'égalité pour que toute paire d'instances dotées des mêmes valeurs de champ teste son égalité au moyen d'une valeur true. Le type GoodAddableType affiche l'implémentation corrigée. Notez que ce type implémente également l'opérateur d'inégalité et se substitue à Equals pour satisfaire d'autres règles. Une implémentation complète implémenterait également 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);
      }
   }
}

L'exemple suivant teste l'égalité au moyen d'instances des types précédemment définis dans cette rubrique, pour illustrer le comportement par défaut et correct de l'opérateur d'égalité.

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

Cet exemple génère la sortie suivante :

Bad type:  {2,2} {2,2} are equal? No
Good type: {3,3} {3,3} are equal? Yes
Good type: {3,3} {3,3} are == ?   Yes
Bad type:  {2,2} {9,9} are equal? No
Good type: {3,3} {9,9} are == ?   No

Voir aussi

Référence

Indications concernant l'implémentation de Equals et de l'opérateur d'égalité (==)