重写可比较类型中的方法

更新: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 的类型。代码注释标识满足与 EqualsIComparable 接口相关的各种规则的方法。

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

请参见

参考

Equals 和相等运算符 (==) 的实现准则

System.IComparable

Object.Equals