CA2020: Gedragswijziging voorkomen die wordt veroorzaakt door ingebouwde operators van IntPtr/UIntPtr

Eigenschap Waarde
Regel-id CA2020
Titel Gedragswijziging voorkomen die wordt veroorzaakt door ingebouwde operators van IntPtr/UIntPtr
Categorie Betrouwbaarheid
Fix kan brekend of niet-brekend zijn Niet-brekend
Standaard ingeschakeld in .NET 10 Als suggestie
Toepasselijke talen C#

Oorzaak

Deze regel wordt geactiveerd wanneer een gedragswijziging tussen .NET 6 en .NET 7 wordt gedetecteerd die is geïntroduceerd door de nieuwe ingebouwde operators van IntPtr en UIntPtr.

Beschrijving van regel

Met de functie numerieke IntPtrIntPtr en UIntPtr ingebouwde operators voor conversies, unaire bewerkingen en binaire bewerkingen. Deze operators kunnen uitzonderingen opwerpen bij overloop in een gecontroleerde context of geen uitzonderingen opwerpen in een niet-gecontroleerde context in vergelijking met de gebruikersgedefinieerde operators in .NET 6 en eerdere versies. U kunt deze gedragswijziging tegenkomen bij het upgraden naar .NET 7.

Lijst met betrokken API's

Operator Context In .NET 7 In .NET 6 en eerder Voorbeeld
operator +(IntPtr, int) gecontroleerd Werpt wanneer overlopen Gooi niet wanneer overloopt checked(intPtrVariable + 2);
operator -(IntPtr, int) aangevinkt Werpt wanneer overlopen Gooit niet bij een overflow checked(intPtrVariable - 2);
explicit operator IntPtr(long) niet aangevinkt Gooit niet bij overflow Kan 32-bits contexten genereren (IntPtr)longVariable;
expliciete operator void*(IntPtr) aangevinkt werpt wanneer overlopen Gooit niet bij overflow checked((void*)intPtrVariable);
expliciete operator IntPtr(void*) gecontroleerd werpt wanneer overlopen Gooit niet bij overflow checked((IntPtr)voidPtrVariable);
expliciete operator int (IntPtr) niet aangevinkt Gooit niet wanneer overlopen Kan 64-bits contexten genereren (int)intPtrVariable;
operator +(UIntPtr, int) gecontroleerd Werpt wanneer overlopen Gooit niet wanneer overlopen checked(uintPtrVariable + 2);
operator -(UIntPtr, int) gecontroleerd Werpt wanneer overlopen Gooit niet wanneer overlopen checked(uintPtrVariable - 2);
expliciete operator UIntPtr(ulong) niet aangevinkt Gooit niet wanneer overlopen Kan 32-bits contexten genereren (UIntPtr)uLongVariable
expliciete operator uint (UIntPtr) niet aangevinkt Gooit niet wanneer overlopen Kan 64-bits contexten genereren (uint)uintPtrVariable

Hoe schendingen op te lossen

Controleer uw code om te bepalen of de gemarkeerde expressie een gedragswijziging kan veroorzaken en kies een geschikte manier om de diagnose op te lossen met de volgende opties:

Herstelopties

  • Als de expressie geen gedragswijziging veroorzaakt:
    • Als het IntPtr of UIntPtr type wordt gebruikt als systeemeigen int of uint, wijzigt u het type in nint of nuint.
    • Als het IntPtr of UIntPtr type wordt gebruikt als systeemeigen aanwijzer, wijzigt u het type in het bijbehorende systeemeigen aanwijzertype.
    • Als u het type variabele niet kunt wijzigen, onderdrukt u de waarschuwing.
  • Als de expressie een gedragswijziging kan veroorzaken, verpakt u de expressie met een checked- of unchecked-instructie om het vorige gedrag te behouden.

Voorbeeld

Schending:

using System;

public unsafe class IntPtrTest
{
    IntPtr intPtrVariable;
    long longVariable;

    void Test ()
    {
        checked
        {
            IntPtr result = intPtrVariable + 2; // Warns: Starting with .NET 7 the operator '+' will throw when overflowing in a checked context. Wrap the expression with an 'unchecked' statement to restore the .NET 6 behavior.

            result = intPtrVariable - 2; // Starting with .NET 7 the operator '-' will throw when overflowing in a checked context. Wrap the expression with an 'unchecked' statement to restore the .NET 6 behavior.

            void* voidPtrVariable = (void*)intPtrVariable; // Starting with .NET 7 the explicit conversion '(void*)IntPtr' will throw when overflowing in a checked context. Wrap the expression with an 'unchecked' statement to restore the .NET 6 behavior.

            result = (IntPtr)voidPtrVariable; // Starting with .NET 7 the explicit conversion '(IntPtr)void*' will throw when overflowing in a checked context. Wrap the expression with an 'unchecked' statement to restore the .NET 6 behavior.
        }

        intPtrVariable = (IntPtr)longVariable; // Starting with .NET 7 the explicit conversion '(IntPtr)Int64' will not throw when overflowing in an unchecked context. Wrap the expression with a 'checked' statement to restore the .NET 6 behavior.

        int a = (int)intPtrVariable; // Starting with .NET 7 the explicit conversion '(Int32)IntPtr' will not throw when overflowing in an unchecked context. Wrap the expression with a 'checked' statement to restore the .NET 6 behavior.
    }
}

Herstel:

  • Als de expressie geen gedragswijziging veroorzaakt en het IntPtr of UIntPtr type wordt gebruikt als systeemeigen int of uint, wijzigt u het type in nint of nuint.
using System;

public unsafe class IntPtrTest
{
    nint intPtrVariable; // type changed to nint
    long longVariable;

    void Test ()
    {
        checked
        {
            nint result = intPtrVariable + 2; // no warning

            result = intPtrVariable - 2;

            void* voidPtrVariable = (void*)intPtrVariable;

            result = (nint)voidPtrVariable;
        }

        intPtrVariable = (nint)longVariable;

        int a = (int)intPtrVariable;
    }
}
  • Als de expressie een gedragswijziging kan veroorzaken, wikkel deze in een checked- of unchecked-verklaring om het vorige gedrag te behouden.
using System;

public unsafe class IntPtrTest
{
    IntPtr intPtrVariable;
    long longVariable;

    void Test ()
    {
        checked
        {
            IntPtr result = unchecked(intPtrVariable + 2); // wrap with unchecked

            result = unchecked(intPtrVariable - 2);

            void* voidPtrVariable = unchecked((void*)intPtrVariable);

            result = unchecked((IntPtr)voidPtrVariable);
        }

        intPtrVariable = checked((IntPtr)longVariable); // wrap with checked

        int a = checked((int)intPtrVariable);
    }
}

Wanneer waarschuwingen onderdrukken

Als de expressie geen gedragswijziging veroorzaakt, is het veilig om een waarschuwing van deze regel te onderdrukken.

Zie ook