Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Property | Värde |
---|---|
Regel-ID | CA2020 |
Title | Förhindra beteendeförändringar som orsakas av inbyggda operatorer av IntPtr/UIntPtr |
Kategori | Tillförlitlighet |
Korrigeringen är icke-bakåtkompatibel | Icke-icke-bryta |
Aktiverad som standard i .NET 9 | Som förslag |
Orsak
Den här regeln utlöses när den identifierar en beteendeförändring mellan .NET 6 och .NET 7 som introduceras av de nya inbyggda operatorerna för IntPtr och UIntPtr.
Regelbeskrivning
Med den IntPtrhar du UIntPtr fått inbyggda operatorer för konverteringar, unary-åtgärder och binära åtgärder. Dessa operatorer kan utlösas när de flödar över i markerad kontext eller kanske inte genererar omarkerad kontext jämfört med tidigare användardefinierade operatorer i .NET 6 och tidigare versioner. Du kan stöta på den här beteendeförändringen när du uppgraderar till .NET 7.
Lista över API:er som påverkas
Operator | Kontext | I .NET 7 | I .NET 6 och tidigare | Exempel |
---|---|---|---|---|
operator +(IntPtr, int) | markerad | Kastar när spill | Kastar inte när spill | checked(intPtrVariable + 2); |
operator -(IntPtr, int) | markerad | Kastar när spill | Kastar inte när spill | checked(intPtrVariable - 2); |
explicit operatorn IntPtr(long) | Okontrollerat | Kastar inte när spill | Kan kasta in 32-bitarskontexter | (IntPtr)longVariable; |
explicit operator void*(IntPtr) | markerad | kastar när spill | Kastar inte när spill | checked((void*)intPtrVariable); |
explicit operator IntPtr(void*) | markerad | kastar när spill | Kastar inte när spill | checked((IntPtr)voidPtrVariable); |
explicit operator int(IntPtr) | Okontrollerat | Kastar inte när spill | Kan kasta in 64-bitarskontexter | (int)intPtrVariable; |
operator +(UIntPtr, int) | markerad | Kastar när spill | Kastar inte när spill | checked(uintPtrVariable + 2); |
operator -(UIntPtr, int) | markerad | Kastar när spill | Kastar inte när spill | checked(uintPtrVariable - 2); |
explicit operator UIntPtr(ulong) | Okontrollerat | Kastar inte när spill | Kan kasta in 32-bitarskontexter | (UIntPtr)uLongVariable |
explicit operator uint(UIntPtr) | Okontrollerat | Kastar inte när spill | Kan kasta in 64-bitarskontexter | (uint)uintPtrVariable |
Så här åtgärdar du överträdelser
Granska koden för att avgöra om det flaggade uttrycket kan orsaka en beteendeförändring och välj ett lämpligt sätt att åtgärda diagnostiken från följande alternativ:
Åtgärda alternativ:
- Om uttrycket inte skulle orsaka en beteendeförändring:
-
IntPtr
Om typen ellerUIntPtr
används som inbyggtint
elleruint
ändrar du typen tillnint
ellernuint
. -
IntPtr
Om typen ellerUIntPtr
används som en inbyggd pekare ändrar du typen till motsvarande inbyggda pekartyp. - Om du inte kan ändra variabeltypen utelämnar du varningen.
-
- Om uttrycket kan orsaka en beteendeförändring kan du omsluta det med en
checked
ellerunchecked
-instruktion för att bevara det tidigare beteendet.
Exempel
Överträdelse:
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.
}
}
Lösningen
- Om uttrycket inte skulle orsaka en beteendeförändring och
IntPtr
typen ellerUIntPtr
används som inbyggtint
elleruint
ändrar du typen tillnint
ellernuint
.
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;
}
}
- Om uttrycket kan orsaka en beteendeförändring kan du omsluta det med en
checked
ellerunchecked
-instruktion för att bevara det tidigare beteendet.
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);
}
}
När du ska ignorera varningar
Om uttrycket inte skulle orsaka en beteendeförändring är det säkert att ignorera en varning från den här regeln.