CA2020: Gedragswijziging voorkomen die wordt veroorzaakt door ingebouwde operators van IntPtr/UIntPtr
Eigenschappen | Weergegeven als |
---|---|
Regel-id | CA2020 |
Titel | Gedragswijziging voorkomen die wordt veroorzaakt door ingebouwde operators van IntPtr/UIntPtr |
Categorie | Betrouwbaarheid |
Oplossing is brekend of niet-brekend | Niet-brekend |
Standaard ingeschakeld in .NET 9 | Als suggestie |
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 overlopen binnen de gecontroleerde context of niet in niet-gecontroleerde context genereren in vergelijking met de vorige door de gebruiker gedefinieerde 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 | Opmerking |
---|---|---|---|---|
operator +(IntPtr, int) | geselecteerd | Werpt wanneer overlopen | Gooit niet wanneer overlopen | checked(intPtrVariable + 2); |
operator -(IntPtr, int) | geselecteerd | Werpt wanneer overlopen | Gooit niet wanneer overlopen | checked(intPtrVariable - 2); |
expliciete operator IntPtr(long) | niet ingeschakeld | Gooit niet wanneer overlopen | Kan 32-bits contexten genereren | (IntPtr)longVariable; |
expliciete operator void*(IntPtr) | geselecteerd | werpt wanneer overlopen | Gooit niet wanneer overlopen | checked((void*)intPtrVariable); |
expliciete operator IntPtr(void*) | geselecteerd | werpt wanneer overlopen | Gooit niet wanneer overlopen | checked((IntPtr)voidPtrVariable); |
expliciete operator int (IntPtr) | niet ingeschakeld | Gooit niet wanneer overlopen | Kan 64-bits contexten genereren | (int)intPtrVariable; |
operator +(UIntPtr, int) | geselecteerd | Werpt wanneer overlopen | Gooit niet wanneer overlopen | checked(uintPtrVariable + 2); |
operator -(UIntPtr, int) | geselecteerd | Werpt wanneer overlopen | Gooit niet wanneer overlopen | checked(uintPtrVariable - 2); |
expliciete operator UIntPtr(ulong) | niet ingeschakeld | Gooit niet wanneer overlopen | Kan 32-bits contexten genereren | (UIntPtr)uLongVariable |
expliciete operator uint (UIntPtr) | niet ingeschakeld | Gooit niet wanneer overlopen | Kan 64-bits contexten genereren | (uint)uintPtrVariable |
Schendingen oplossen
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:
Oplossingsopties:
- Als de expressie geen gedragswijziging veroorzaakt:
- Als het
IntPtr
ofUIntPtr
type wordt gebruikt als systeemeigenint
ofuint
, wijzigt u het type innint
ofnuint
. - Als het
IntPtr
ofUIntPtr
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 het
- Als de expressie een gedragswijziging kan veroorzaken, verpakt u deze met een
checked
ofunchecked
een instructie om het vorige gedrag te behouden.
Opmerking
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.
}
}
Oplossing:
- Als de expressie geen gedragswijziging veroorzaakt en het
IntPtr
ofUIntPtr
type wordt gebruikt als systeemeigenint
ofuint
, wijzigt u het type innint
ofnuint
.
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, verpakt u deze met een
checked
ofunchecked
een instructie 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.