Aracılığıyla paylaş


CA1036: Karşılaştırılabilir türlerde geçersiz kılma yöntemleri

Özellik Değer
Kural Kimliği CA1036
Başlık Karşılaştırılabilir türlerde metotları geçersiz kıl
Kategori Tasarım
Hataya neden olan veya bozulmayan düzeltme Hataya neden olmayan
.NET 8'de varsayılan olarak etkin Hayır

Neden

Bir tür arabirimi uygular System.IComparable ve eşitlik, eşitsizlik, küçüktür veya büyüktür için dile özgü işleci geçersiz kılmaz System.Object.Equals veya aşırı yüklemez. Tür yalnızca arabirimin bir uygulamasını devralıyorsa kural bir ihlal bildirmez.

Varsayılan olarak, bu kural yalnızca dışarıdan görünen türlere bakar, ancak bu yapılandırılabilir.

Kural açıklaması

Özel sıralama düzeni tanımlayan türler arabirimini IComparable uygular. yöntemi, CompareTo türün iki örneği için doğru sıralama düzenini gösteren bir tamsayı değeri döndürür. Bu kural, sıralama düzeni ayarlayan türleri tanımlar. Sıralama düzeni ayarlamak, eşitlik, eşitsizlik, küçüktür ve büyüktür gibi normal anlamının geçerli olmadığı anlamına gelir. uygulamasını IComparablesağladığınızda, genellikle ile CompareTotutarlı değerler döndürmesi için de geçersiz kılmanız Equals gerekir. Geçersiz kılarsanız Equals ve işleç aşırı yüklemelerini destekleyen bir dilde kodlama yaparsanız, ile Equalstutarlı işleçler de sağlamanız gerekir.

İhlalleri düzeltme

Bu kuralın ihlalini düzeltmek için geçersiz kılın Equals. Programlama diliniz işleç aşırı yüklemesini destekliyorsa aşağıdaki işleçleri sağlayın:

  • op_Equality
  • op_Inequality
  • op_LessThan
  • op_GreaterThan

C# dilinde, bu işleçleri temsil etmek için kullanılan belirteçler aşağıdaki gibidir:

==
!=
<
>

Uyarıların ne zaman bastırılması gerekiyor?

İhlal eksik işleçlerden kaynaklandığında ve programlama diliniz Visual Basic'de olduğu gibi işleç aşırı yüklemesini desteklemediğinde CA1036 kuralından gelen bir uyarıyı bastırmak güvenlidir. İşleçleri uygulamanın uygulama bağlamında anlamlı olmadığını belirlerseniz, op_Equality dışındaki eşitlik işleçlerinde tetiklendiğinde bu kuraldan gelen bir uyarıyı gizlemeniz de güvenlidir. Ancak, geçersiz kılarsanız her zaman op_Equality ve == işlecini geçersiz kılmalısınız Object.Equals.

Uyarıyı gizleme

Yalnızca tek bir ihlali engellemek istiyorsanız, kuralı devre dışı bırakmak ve sonra yeniden etkinleştirmek için kaynak dosyanıza ön işlemci yönergeleri ekleyin.

#pragma warning disable CA1036
// The code that's violating the rule is on this line.
#pragma warning restore CA1036

Bir dosya, klasör veya projenin kuralını devre dışı bırakmak için, yapılandırma dosyasındaki önem derecesini noneolarak ayarlayın.

[*.{cs,vb}]
dotnet_diagnostic.CA1036.severity = none

Daha fazla bilgi için bkz . Kod analizi uyarılarını gizleme.

Çözümlemek için kod yapılandırma

Bu kuralın kod tabanınızın hangi bölümlerinde çalıştırılacaklarını yapılandırmak için aşağıdaki seçeneği kullanın.

Bu seçeneği yalnızca bu kural, geçerli olduğu tüm kurallar veya bu kategorideki (Tasarım) tüm kurallar için yapılandırabilirsiniz. Daha fazla bilgi için bkz . Kod kalitesi kuralı yapılandırma seçenekleri.

Belirli API yüzeylerini ekleme

Bu kuralın üzerinde çalıştırılacak kod tabanınızın hangi bölümlerini erişilebilirliklerine göre yapılandırabilirsiniz. Örneğin, kuralın yalnızca genel olmayan API yüzeyinde çalıştırılması gerektiğini belirtmek için projenizdeki bir .editorconfig dosyasına aşağıdaki anahtar-değer çiftini ekleyin:

dotnet_code_quality.CAXXXX.api_surface = private, internal

Örnekler

Aşağıdaki kod doğru şekilde uygulayan IComparablebir tür içerir. Kod açıklamaları ve IComparable arabirimiyle ilgili Equals çeşitli kuralları karşılayan yöntemleri tanımlar.

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

Aşağıdaki uygulama kodu, daha önce gösterilen uygulamanın davranışını IComparable test ediyor.

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

Ayrıca bkz.