Freigeben über


CA1036: Methoden bei vergleichbaren Typen überschreiben

TypeName

OverrideMethodsOnComparableTypes

CheckId

CA1036

Kategorie (Category)

Microsoft.Design

Unterbrechende Änderung

Nicht unterbrechend

Ursache

Von einem öffentlichen oder geschützten Typ wird die IComparable-Schnittstelle implementiert. Object.Equals wird jedoch nicht überschrieben, bzw. die sprachspezifischen Operatoren für Gleichheit, Ungleichheit, Kleiner als oder Größer als werden nicht überladen.Die Regel meldet keinen Verstoß, wenn der Typ nur eine Implementierung der Schnittstelle erbt.

Regelbeschreibung

Typen, die eine benutzerdefinierte Sortierreihenfolge definieren, implementieren die IComparable-Schnittstelle.Die CompareTo-Methode gibt einen Ganzzahlwert zurück, der die richtige Sortierreihenfolge für zwei Instanzen des Typs angibt.Diese Regel identifiziert Typen, die eine Sortierreihenfolge festlegen. Dies impliziert, dass die gewöhnliche Bedeutung von Gleichheit, Ungleichheit, kleiner als und größer als nicht gilt.Wenn Sie eine Implementierung von IComparable angeben, muss in der Regel auch Equals überschrieben werden, damit Werte zurückgegeben werden, die mit CompareTo konsistent sind.Wenn Sie Equals überschreiben und den Programmcode in einer Sprache schreiben, die Operatorüberladungen unterstützt, müssen Sie auch Operatoren angeben, die mit Equals konsistent sind.

Behandeln von Verstößen

Um einen Verstoß gegen diese Regel zu korrigieren, überschreiben Sie Equals.Wenn die Programmiersprache das Überladen von Operatoren unterstützt, geben Sie die folgenden Operatoren an:

  • op_Equality

  • op_Inequality

  • op_LessThan

  • op_GreaterThan

In C# sind die Token, die verwendet werden, um anzuzeigen, diese Operatoren, wie folgt: ==! =, <und >.

Wann sollten Warnungen unterdrückt werden?

Eine Warnung dieser Regel kann gefahrlos unterdrückt werden, wenn der Verstoß durch fehlende Operatoren verursacht wird und die Programmiersprache das Überladen von Operatoren nicht unterstützt, wie dies bei Visual Basic .NET der Fall ist.Es ist auch sicher, eine Warnung für diese Regel zu unterdrücken, wenn sie bei anderen Gleichheitsoperatoren als op_Equality ausgelöst wird, falls Sie entscheiden, dass eine Implementierung der Operatoren im Anwendungskontext keinen Sinn ergibt.Sie sollten jedoch immer op_Equality und den ==-Operator überschreiben, wenn Sie Object.Equals überschreiben.

Beispiel

Das folgende Beispiel enthält einen Typ, von dem IComparable ordnungsgemäß implementiert wird.Codekommentare identifizieren die Methoden, die verschiedenen Regeln entsprechen, die sich auf Equals und auf die IComparable-Schnittstelle beziehen.

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

Die folgende Anwendung testet das Verhalten der weiter oben dargestellten IComparable-Implementierung.

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

Siehe auch

Referenz

IComparable

Object.Equals

Weitere Ressourcen

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