CA1036:重写可比较类型中的方法
类型名 |
OverrideMethodsOnComparableTypes |
CheckId |
CA1036 |
类别 |
Microsoft.Design |
是否重大更改 |
非重大更改 |
原因
公共或受保护类型实现 System.IComparable 接口,不重写 Object.Equals,也不重载表示相等、不等、小于或大于的语言特定的运算符。 如果该类型仅继承接口的实现,则该规则不会报告冲突。
规则说明
定义自定义排序顺序的类型实现 IComparable 接口。 CompareTo 方法返回一个整数值,指示该类型的两个实例的正确排序顺序。 该值标识设置排序顺序的类型;这意味着不会应用相等、不等、小于或大于的常规含义。 提供 IComparable 的实现时,通常还必须重写 Equals,以使其返回与 CompareTo 一致的值。 如果重写 Equals 并使用支持运算符重载的语言编写代码,则还应提供与 Equals 一致的运算符。
如何解决冲突
要修复与该规则的冲突,请重写 Equals。 如果您的编程语言支持运算符重载,请提供下列运算符:
op_Equality
op_Inequality
op_LessThan
op_GreaterThan
在 C# 中,用来代表这些运算符的标记如下所示:==、!=、< 和 >。
何时禁止显示警告
如果冲突是因缺少运算符引起的,且您的编程语言不支持运算符重载(例如,在 Visual Basic .NET 中就是这样),则可以安全地禁止显示此规则发出的警告。 如果您确定实现相等运算符在应用程序上下文中没有意义,则当 op_Equality 以外相等运算符上激发此规则时,禁止此规则的显示也是安全的。 但是,如果重写 Object.Equals,应该始终重写 op_Equality 和 == 运算符。
示例
下面的示例包含正确实现 IComparable 的类型。 代码注释标识满足与 Equals 和 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);
}
}
}
下面的应用程序测试上文所示的 IComparable 实现的行为。
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);
}
}
}
请参见
参考
Guidelines for Implementing Equals and the Equality Operator (==)