重写可比较类型中的方法
更新:2007 年 11 月
TypeName |
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 中就是这样),则可以安全地禁止显示此规则发出的警告。
示例
下面的示例包含正确实现 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
{
private string rating;
public RatingInformation (string s)
{
string v = s.ToUpper(CultureInfo.InvariantCulture);
if (v.CompareTo("C") > 0 || v.CompareTo("A") < 0 || v.Length != 1)
{
throw new ArgumentException("Invalid rating value was specified.");
}
rating = v;
}
public int CompareTo ( object obj)
{
if (!(obj is RatingInformation))
{
throw new ArgumentException(
"A RatingInformation object is required for comparison.");
}
// Ratings compare opposite to normal string order,
// so reverse the value returned by String.CompareTo.
return -1 * this.rating.CompareTo(((RatingInformation)obj).rating);
}
public string Rating
{
get { return rating;}
}
// Omitting Equals violates rule: OverrideMethodsOnComparableTypes.
public override bool Equals (Object obj)
{
if (!(obj is RatingInformation))
return false;
return (this.CompareTo(obj)== 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 r1, RatingInformation r2)
{
return r1.Equals(r2);
}
public static bool operator != (RatingInformation r1, RatingInformation r2)
{
return !(r1==r2);
}
public static bool operator < (RatingInformation r1, RatingInformation r2)
{
return (r1.CompareTo(r2) < 0);
}
public static bool operator > (RatingInformation r1, RatingInformation r2)
{
return (r1.CompareTo(r2) > 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);
}
}
}