Partilhar via


CA1036: substituir métodos em tipos comparáveis

TypeName

OverrideMethodsOnComparableTypes

CheckId

CA1036

Categoria

Microsoft.Design

Alteração Significativa

Sem quebra

Causa

Um público ou um tipo protegido implementam a interface de IComparable e não substitui Object.Equals nem sobrecarregam o operador específico do idioma para igualdade, desigualdade, menor que, ou maior que.A regra não informa uma violação se o tipo herda apenas uma implementação da interface.

Descrição da Regra

Define um tipo que implementam personalizado da ordem de classificação a interface de IComparable .O método de CompareTo retorna um valor inteiro que indica a ordem de classificação correta para duas instâncias do tipo.Esta regra identificará os tipos que definem uma ordem de classificação; isso significa que o significado comum de igualdade, desigualdade, menor que, e maior do que não se apliquem.Quando você fornece uma implementação de IComparableem geral, você deve também substituir Equals de modo que retorna os valores que são consistentes com CompareTo.Se você substituir Equals e o está codificando em um idioma com suporte sobrecargas do operador, você também deve fornecer os operadores que são consistentes com Equals.

Como Corrigir Violações

Para corrigir uma violação desta regra, substitua Equals.Se a linguagem de programação da suporte ao sobrecarregamento de operador, forneça 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 os seguintes: ==! = <, e >.

Quando Suprimir Alertas

É seguro suprimir um aviso desta regra quando a violação é causada por operadores ausentes e a linguagem de programação não oferece suporte ao sobrecarregamento de operador, como é o caso com o Visual Basic .NET.Também é seguro para suprimir um aviso desta regra quando é acionado em operadores de igualdade diferentes de op_Equality se você verificar que implementa os operadores não faz sentido no contexto do aplicativo.Porém, você deve sempre sobre o op_Equality e o operador == se você substituir Object.Equals.

Exemplo

O exemplo a seguir contém um tipo que implementa IComparablecorretamente.Os comentários de código identificam os métodos que satisfazem as várias regras relacionadas a Equals e a interface de 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, 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 aplicativo seguir testa o comportamento da implementação de IComparable 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

IComparable

Object.Equals

Outros recursos

Guidelines for Implementing Equals and the Equality Operator (==)