Reemplazar métodos en tipos comparables

Actualización: noviembre 2007

Nombre de tipo

OverrideMethodsOnComparableTypes

Identificador de comprobación

CA1036

Categoría

Microsoft.Design

Cambio problemático

No problemático

Motivo

Un tipo público o protegido implementa la interfaz System.IComparable y no reemplaza Object.Equals ni sobrecarga el operador específico del leguaje por uno de igualdad, desigualdad o mayor que él. La regla no informa de una infracción si el tipo sólo hereda una implementación de la interfaz.

Descripción de la regla

Los tipos que definen un criterio de ordenación personalizado implementan la interfaz IComparable. El método CompareTo devuelve un valor entero que indica el criterio de ordenación adecuado para dos instancias del tipo. Esta regla identifica los tipos que establecen el criterio de ordenación, que implica que no se aplique el criterio ordinario de igualdad, desigualdad, menor o mayor que. Al proporcionar una implementación de IComparable, normalmente también es necesario reemplazar Equals de modo que devuelva los valores coherentes con CompareTo. Si reemplaza Equals y está codificando en un lenguaje que admite las sobrecargas de operador, también debería proporcionar operadores coherentes con Equals.

Cómo corregir infracciones

Para corregir una infracción de esta regla, reemplace Equals. Si su lenguaje de programación admite la sobrecarga de operadores, proporcione los operadores siguientes:

  • op_Equality

  • op_Inequality

  • op_LessThan

  • op_GreaterThan

En C#, los símbolos (token) utilizados para representar estos operadores son: ==, !=, < y >.

Cuándo suprimir advertencias

Es seguro suprimir una advertencia de esta regla cuando la causan los operadores que faltan y el lenguaje de programación no admite la sobrecarga de operadores, como es el caso de Visual Basic .NET.

Ejemplo

El ejemplo siguiente contiene un tipo que implementa IComparable correctamente. ‎Los comentarios de código identifican los métodos que cumplen las distintas reglas relacionadas con Equals y la interfaz IComparable.

using System;
using System.Globalization;

namespace DesignLibrary
{
   // Valid ratings are between A and C.
   // A is the highest rating; it is greater than any other valid rating.
   // C is the lowest rating; it is less than any other valid rating.

   public class RatingInformation :IComparable 
   {
      private string rating;

      public RatingInformation (string s)
      {
         string v = s.ToUpper(CultureInfo.InvariantCulture);
         if (v.CompareTo("C") > 0 || v.CompareTo("A") < 0 || v.Length != 1)
         {
            throw new ArgumentException("Invalid rating value was specified.");
         }
         rating = v;
      }

      public int CompareTo ( object obj)
      {
         if (!(obj is RatingInformation))
         {
            throw new ArgumentException(
               "A RatingInformation object is required for comparison.");
         }
         // Ratings compare opposite to normal string order,
         // so reverse the value returned by String.CompareTo.
         return -1 * this.rating.CompareTo(((RatingInformation)obj).rating);
      }

      public string Rating 
      {
         get { return rating;}
      }

      // Omitting Equals violates rule: OverrideMethodsOnComparableTypes.
      public override bool Equals (Object obj)
      {
         if (!(obj is RatingInformation))
            return false;
         return (this.CompareTo(obj)== 0);
      }  

      // Omitting getHashCode violates rule: OverrideGetHashCodeOnOverridingEquals.
      public override int GetHashCode ()
      {
         char [] c = this.Rating.ToCharArray();
         return (int) c[0];
      }  
      // Omitting any of the following operator overloads 
      // violates rule: OverrideMethodsOnComparableTypes.
      public static bool operator == (RatingInformation r1, RatingInformation r2)
      {
         return r1.Equals(r2);
      }  
      public static bool operator != (RatingInformation r1, RatingInformation r2)
      {
        return !(r1==r2);
      }  
      public static bool operator < (RatingInformation r1, RatingInformation r2)
      {
         return (r1.CompareTo(r2) < 0);
      }  
      public static bool operator > (RatingInformation r1, RatingInformation r2)
      {
         return (r1.CompareTo(r2) > 0);
      }  
   }
}

La aplicación siguiente prueba el comportamiento de la implementación IComparable mostrado anteriormente.

using System;

namespace DesignLibrary
{
    public class Test
    {
       public static void Main(string [] args)
       {
          if (args.Length < 2)
          {
             Console.WriteLine ("usage - TestRatings  string 1 string2");
             return;
          }
          RatingInformation r1 = new RatingInformation(args[0]) ;
          RatingInformation r2 = new RatingInformation( args[1]);
          string answer;

          if (r1.CompareTo(r2) > 0)
             answer = "greater than";
          else if (r1.CompareTo(r2) < 0)
             answer = "less than";
          else
             answer = "equal to";

          Console.WriteLine("{0} is {1} {2}", r1.Rating, answer, r2.Rating);      
       }
    }
}

Vea también

Referencia

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

System.IComparable

Object.Equals