Delen via


CA1036: Methoden overschrijven voor vergelijkbare typen

Eigenschappen Weergegeven als
Regel-id CA1036
Titel Onderdrukkingsmethoden voor vergelijkbare typen
Categorie Ontwerpen
Oplossing is brekend of niet-brekend Niet-brekend
Standaard ingeschakeld in .NET 8 Nee

Oorzaak

Een type implementeert de System.IComparable interface en overschrijft System.Object.Equals de taalspecifieke operator niet voor gelijkheid, ongelijkheid, kleiner dan of groter dan. De regel rapporteert geen schending als het type alleen een implementatie van de interface over neemt.

Deze regel kijkt standaard alleen naar extern zichtbare typen, maar dit kan worden geconfigureerd.

Beschrijving van regel

Typen die een aangepaste sorteervolgorde definiëren, implementeren de IComparable interface. De CompareTo methode retourneert een geheel getal dat de juiste sorteervolgorde aangeeft voor twee exemplaren van het type. Deze regel identificeert typen die een sorteervolgorde instellen. Het instellen van een sorteervolgorde impliceert dat de gewone betekenis van gelijkheid, ongelijkheid, kleiner dan en groter dan niet van toepassing is. Wanneer u een implementatie opgeeft IComparable, moet u meestal ook overschrijven Equals zodat deze waarden retourneert die consistent zijn met CompareTo. Als u overschrijft Equals en codeert in een taal die overbelasting van operatoren ondersteunt, moet u ook operators opgeven die consistent zijn met Equals.

Schendingen oplossen

Als u een schending van deze regel wilt oplossen, overschrijft Equalsu . Als uw programmeertaal overbelasting van operatoren ondersteunt, moet u de volgende operators opgeven:

  • op_Equality
  • op_Inequality
  • op_LessThan
  • op_GreaterThan

In C# zijn de tokens die worden gebruikt om deze operators weer te geven als volgt:

==
!=
<
>

Wanneer waarschuwingen onderdrukken

Het is veilig om een waarschuwing van regel CA1036 te onderdrukken wanneer de schending wordt veroorzaakt door ontbrekende operators en uw programmeertaal geen ondersteuning biedt voor overbelasting van operatoren, zoals het geval is bij Visual Basic. Als u vaststelt dat het implementeren van de operators niet zinvol is in uw app-context, is het ook veilig om een waarschuwing van deze regel te onderdrukken wanneer deze wordt geactiveerd op andere gelijkheidsoperators dan op_Equality. U moet echter altijd op_Equality en de operator == overschrijven als u overschrijft Object.Equals.

Een waarschuwing onderdrukken

Als u slechts één schending wilt onderdrukken, voegt u preprocessorrichtlijnen toe aan uw bronbestand om de regel uit te schakelen en vervolgens opnieuw in te schakelen.

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

Als u de regel voor een bestand, map of project wilt uitschakelen, stelt u de ernst none ervan in op het configuratiebestand.

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

Zie Codeanalysewaarschuwingen onderdrukken voor meer informatie.

Code configureren om te analyseren

Gebruik de volgende optie om te configureren op welke onderdelen van uw codebase deze regel moet worden uitgevoerd.

U kunt deze optie configureren voor alleen deze regel, voor alle regels waarop deze van toepassing is, of voor alle regels in deze categorie (ontwerp) waarop deze van toepassing is. Zie de configuratieopties voor de codekwaliteitsregel voor meer informatie.

Specifieke API-oppervlakken opnemen

U kunt instellen op welke onderdelen van uw codebase deze regel moet worden uitgevoerd, op basis van hun toegankelijkheid. Als u bijvoorbeeld wilt opgeven dat de regel alleen moet worden uitgevoerd op het niet-openbare API-oppervlak, voegt u het volgende sleutel-waardepaar toe aan een .editorconfig-bestand in uw project:

dotnet_code_quality.CAXXXX.api_surface = private, internal

Voorbeelden

De volgende code bevat een type dat correct wordt geïmplementeerd IComparable. Codeopmerkingen identificeren de methoden die voldoen aan verschillende regels die zijn gerelateerd aan Equals en de IComparable interface.

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

Met de volgende toepassingscode wordt het gedrag getest van de IComparable implementatie die eerder is weergegeven.

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

Zie ook