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
Weitere Ressourcen
Guidelines for Implementing Equals and the Equality Operator (==)