Compartir a través de


Sobrecargar el operador de igualdad al sobrecargar los operadores de suma y resta

Actualización: noviembre 2007

Nombre de tipo

OverloadOperatorEqualsOnOverloadingAddAndSubtract

Identificador de comprobación

CA1013

Categoría

Microsoft.Design

Cambio problemático

No problemático

Motivo

Un tipo público o protegido implementa los operadores de suma o resta sin implementar el operador de igualdad.

Descripción de la regla

Cuando las instancias de un tipo se combinan utilizando estos operadores de suma o resta, casi siempre se debe definir la igualdad para devolver true para cualquiera de las dos instancias que tienen los mismo valores constituyentes.

No puede utilizar el operador de igualdad predeterminado en una implementación sobrecargada del operador de igualdad. Con ello se producirá un desbordamiento de pila. Para implementar el operador de igualdad, utilice el método Object.Equals en la implementación. Por ejemplo:

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

Cómo corregir infracciones

Para corregir una infracción de esta regla, implemente al operador de igualdad para que sea matemáticamente coherente con los operadores de suma y resta.

Cuándo suprimir advertencias

Es seguro suprimir una advertencia de esta regla cuando la implementación predeterminada del operador de igualdad proporciona el comportamiento adecuado para el tipo.

Ejemplo

El siguiente ejemplo se define un tipo (BadAddableType) que infringe esta regla. Este tipo debe implementar el operador de igualdad para que al comparar los mismos campos de dos instancias cualquiera devuelva true cuando los valores sean iguales. El tipo GoodAddableType muestra la implementación correcta. Observe que este tipo también implementa al operador de desigualdad y reemplaza Equals para cumplir otras reglas. Una implementación completa también implementaría 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);
      }
   }
}

En el siguiente ejemplo se comprueba la igualdad utilizando instancias de los tipos definidos anteriormente en este tema para mostrar el comportamiento correcto y el comportamiento predeterminado del operador de igualdad.

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

Este ejemplo produce el siguiente resultado.

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

Vea también

Referencia

Instrucciones para implementar Equals y el operador de igualdad (==)