更新 : 2007 年 11 月
TypeName |
OverrideMethodsOnComparableTypes |
CheckId |
CA1036 |
カテゴリ |
Microsoft.Design |
互換性に影響する変更点 |
なし |
原因
パブリック型またはプロテクト型で System.IComparable インターフェイスが実装されています。これによって Object.Equals はオーバーライドされません。また、"等しい"、"等しくない"、"未満"、"より大きい" を示す言語固有の演算子はオーバーロードされません。型でインターフェイスの実装を継承しているだけの場合、この規則違反はレポートされません。
規則の説明
カスタムの並べ替え順序を定義する型では、IComparable インターフェイスを実装します。CompareTo メソッドは、その型の 2 つのインスタンスについて、適切な並べ替え順序を示す整数値を返します。この規則では、並べ替え順序を設定する型を識別します。つまり、一般的な意味の "等しい"、"等しくない"、"未満"、"より大きい" は適用されません。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);
}
}
}