Compartilhar via


CA1036: Substituir os métodos de tipos comparáveis

TypeName

OverrideMethodsOnComparableTypes

CheckId

CA1036

<strong>Categoria</strong>

Microsoft.design

Alteração significativa

Não-separável

Causa

Um tipo de público ou protegido implementa o System.IComparable interface e não substitui Object.Equals ou não sobrecarregar o operador específicos do idioma de igualdade, desigualdade, menor ou maior. A regra não relatar uma violação, se o tipo herda somente uma implementação da interface.

Descrição da regra

Tipos de definem uma ordem de classificação personalizada implementam a IComparable interface. O CompareTo método retorna um valor inteiro que indica a ordem de classificação correta de duas instâncias do tipo. Esta regra identifica os tipos de definir uma ordem de classificação; Isso implica que o significado comum de igualdade, desigualdade, menor e maior que não se aplicam. Quando você fornecer uma implementação de IComparable, você geralmente deve também substituir Equals para que ele retorne valores que são consistentes com CompareTo. Se você substituir Equals e está codificando em uma linguagem que suporta as sobrecargas de operador, você também deve fornecer os operadores são consistentes com Equals.

Como corrigir violações

Para corrigir uma violação desta regra, substitua Equals. Se a sua linguagem de programação oferece suporte a sobrecarga de operador, fornece os seguintes operadores:

  • op_Equality

  • op_Inequality

  • op_LessThan

  • op_GreaterThan

No C#, os tokens que são usados para representar esses operadores são: = =,! =, <, e >.

Quando suprimir avisos

É seguro eliminar um aviso esta regra quando a violação é causada por falta de operadores e sua linguagem de programação não oferece suporte a sobrecarga de operador, assim como acontece com Visual Basic.NET. Também é seguro eliminar um aviso para esta regra quando ela for acionado em operadores de igualdade diferente, por exemplo, op_Equality, se você determinar que os operadores de implementação não faz sentido no contexto de seu aplicativo. No entanto, você deve sempre pela op_Equality e o operador = = se você substitui Object. Equals.

Exemplo

O exemplo a seguir contém um tipo que implementa corretamente IComparable. Comentários de código identificam os métodos que satisfaçam várias regras que são relacionadas a Equals e o IComparable interface.

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, IComparable<RatingInformation>
    {
        public string Rating
        {
            get;
            private set;
        }

        public RatingInformation(string rating)
        {
            if (rating == null)
            {
                throw new ArgumentNullException("rating");
            }
            string v = rating.ToUpper(CultureInfo.InvariantCulture);
            if (v.Length != 1 || string.Compare(v, "C", StringComparison.Ordinal) > 0 || string.Compare(v, "A", StringComparison.Ordinal) < 0)
            {
                throw new ArgumentException("Invalid rating value was specified.", "rating");
            }
            this.Rating = v;
        }

        public int CompareTo(object obj)
        {
            if (obj == null)
            {
                return 1;
            }
            RatingInformation other = obj as RatingInformation; // avoid double casting
            if (other == null)
            {
                throw new ArgumentException("A RatingInformation object is required for comparison.", "obj");
            }
            return this.CompareTo(other);
        }

        public int CompareTo(RatingInformation other)
        {
            if (object.ReferenceEquals(other, null))
            {
                return 1;
            }
            // Ratings compare opposite to normal string order, 
            // so reverse the value returned by String.CompareTo.
            return -string.Compare(this.Rating, other.Rating, StringComparison.OrdinalIgnoreCase);
        }

        public static int Compare(RatingInformation left, RatingInformation right)
        {
            if (object.ReferenceEquals(left, right))
            {
                return 0;
            }
            if (object.ReferenceEquals(left, null))
            {
                return -1;
            }
            return left.CompareTo(right);
        }

        // Omitting Equals violates rule: OverrideMethodsOnComparableTypes.
        public override bool Equals(object obj)
        {
            RatingInformation other = obj as RatingInformation; //avoid double casting
            if (object.ReferenceEquals(other, null))
            {
                return false;
            }
            return this.CompareTo(other) == 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 left, RatingInformation right)
        {
            if (object.ReferenceEquals(left, null))
            {
                return object.ReferenceEquals(right, null);
            }
            return left.Equals(right);
        }
        public static bool operator !=(RatingInformation left, RatingInformation right)
        {
            return !(left == right);
        }
        public static bool operator <(RatingInformation left, RatingInformation right)
        {
            return (Compare(left, right) < 0);
        }
        public static bool operator >(RatingInformation left, RatingInformation right)
        {
            return (Compare(left, right) > 0);
        }
    }
}

O seguinte aplicativo testa o comportamento da IComparable implementação que foi mostrada 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);      
       }
    }
}

Consulte também

Referência

Diretrizes para a implementação de Equals e o operador de igualdade (= =)

System.IComparable

Object.Equals