CA1036:必須在 Comparable 類型中覆寫方法
屬性 | 值 |
---|---|
規則識別碼 | CA1036 |
標題 | 必須在 Comparable 類型中覆寫方法 |
類別 | 設計 |
修正程式是中斷或非中斷 | 不中斷 |
預設在 .NET 8 中啟用 | No |
原因
類型會實作 System.IComparable 介面,且不會覆寫 System.Object.Equals 或未多載語言特定運算子,以取得相等、不相等、小於或大於。 如果型別只繼承介面的實作,規則不會報告違規。
根據預設,此規則只會查看外部可見的類型,但這是可設定 的 。
檔案描述
定義自訂排序次序的類型會實作 IComparable 介面。 方法 CompareTo 會傳回整數值,指出型別兩個實例的正確排序次序。 此規則會識別設定排序次序的類型。 設定排序次序表示相等、不相等、小於和大於的一般意義不適用。 當您提供 的 IComparable 實作時,通常也必須覆寫 Equals ,使其傳回與 CompareTo 一致的值。 如果您以支援運算子多載的語言覆寫 Equals 和撰寫程式碼,則也應該提供與 Equals 一致的運算子。
如何修正違規
若要修正此規則的違規,請覆寫 Equals 。 如果您的程式設計語言支援運算子多載,請提供下列運算子:
- op_Equality
- op_Inequality
- op_LessThan
- op_GreaterThan
在 C# 中,用來表示這些運算子的權杖如下所示:
==
!=
<
>
隱藏警告的時機
當違規是由遺漏運算子所造成,且您的程式設計語言不支援運算子多載時,隱藏來自規則 CA1036 的警告,就像 Visual Basic 的情況一樣。 如果您判斷實作運算子在應用程式內容中沒有意義,在引發非op_Equality的等號運算子時,隱藏此規則的警告也是安全的。 不過,如果您覆 Object.Equals 寫 ,您應該一律覆寫 op_Equality 和 == 運算子。
隱藏警告
如果您只想要隱藏單一違規,請將預處理器指示詞新增至原始程式檔以停用,然後重新啟用規則。
#pragma warning disable CA1036
// The code that's violating the rule is on this line.
#pragma warning restore CA1036
若要停用檔案、資料夾或專案的規則,請在組態檔 中將其嚴重性設定為 。 none
[*.{cs,vb}]
dotnet_diagnostic.CA1036.severity = none
如需詳細資訊,請參閱 如何隱藏程式碼分析警告 。
設定程式碼以分析
使用下列選項來設定程式碼基底要執行此規則的部分。
您可以只針對此規則、針對它套用的所有規則,或針對套用至此類別的所有規則, 或針對它套用的所有規則,設定此選項。 如需詳細資訊,請參閱 程式碼品質規則組態選項 。
包含特定 API 介面
您可以根據程式碼基底的存取範圍,設定要執行此規則的部分。 例如,若要指定規則只應該針對非公用 API 介面執行,請將下列機碼/值組新增至 專案中的 .editorconfig 檔案:
dotnet_code_quality.CAXXXX.api_surface = private, internal
範例
下列程式碼包含可正確實作 IComparable 的型別。 程式碼批註會識別滿足與 Equals 和 IComparable 介面相關之各種規則的方法。
// 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");
}
Rating = v;
}
public int CompareTo(object? obj)
{
if (obj == null)
{
return 1;
}
if (obj is RatingInformation other)
{
return CompareTo(other);
}
throw new ArgumentException("A RatingInformation object is required for comparison.", "obj");
}
public int CompareTo(RatingInformation? other)
{
if (other is 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 (left is null)
{
return -1;
}
return left.CompareTo(right);
}
// Omitting Equals violates rule: OverrideMethodsOnComparableTypes.
public override bool Equals(object? obj)
{
if (obj is RatingInformation other)
{
return this.CompareTo(other) == 0;
}
return false;
}
// 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 (left is null)
{
return right is 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 的行為。
public class Test
{
public static void Main1036(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);
}
}