Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
| Properti | Nilai |
|---|---|
| ID Aturan | CA2020 |
| Judul | Mencegah perubahan perilaku yang disebabkan oleh operator bawaan IntPtr/UIntPtr |
| Kategori | Keandalan |
| Perbaikan bersifat merusak atau tidak merusak | Tidak terputus |
| Diaktifkan secara default di .NET 10 | Sebagai saran |
| Bahasa yang berlaku | C# |
Penyebab
Aturan ini diaktifkan ketika mendeteksi perubahan perilaku antara .NET 6 dan .NET 7 yang disebabkan oleh operator bawaan baru IntPtr dan UIntPtr.
Deskripsi aturan
Dengan fitur IntPtr numerik, IntPtr dan UIntPtr mendapatkan operator bawaan untuk konversi, operasi unary, dan operasi biner. Operator ini mungkin melempar saat meluap dalam konteks yang diperiksa atau mungkin tidak dilemparkan dalam konteks yang tidak dicentang dibandingkan dengan operator yang ditentukan pengguna sebelumnya di .NET 6 dan versi yang lebih lama. Anda mungkin mengalami perubahan perilaku ini saat memutakhirkan ke .NET 7.
Daftar API yang terpengaruh
| Operator | Konteks | Dalam .NET 7 | Di .NET 6 dan yang lebih lama | Contoh |
|---|---|---|---|---|
| operator +(IntPtr, int) | dicentang | Melempar ketika luapan | Tidak melempar ketika luapan | checked(intPtrVariable + 2); |
| operator -(IntPtr, int) | diperiksa | Melempar ketika luapan | Tidak melempar ketika luapan | checked(intPtrVariable - 2); |
| Operator eksplisit IntPtr(long) | yang tidak dicentang | Tidak melempar ketika luapan | Dapat melemparkan dalam konteks 32-bit | (IntPtr)longVariable; |
| operator eksplisit batal*(IntPtr) | dicentang | melempar ketika luapan | Tidak melempar ketika luapan | checked((void*)intPtrVariable); |
| operator eksplisit IntPtr(void*) | ditandai | melempar ketika luapan | Tidak melempar ketika luapan | checked((IntPtr)voidPtrVariable); |
| operator eksplisit int(IntPtr) | tidak dicentang | Tidak melempar ketika luapan | Dapat melakukan throw dalam konteks 64-bit | (int)intPtrVariable; |
| operator +(UIntPtr, int) | dicentang | Melempar ketika luapan | Tidak melempar ketika luapan | checked(uintPtrVariable + 2); |
| operator -(UIntPtr, int) | dicentang | Melempar ketika luapan | Tidak melempar ketika luapan | checked(uintPtrVariable - 2); |
| operator eksplisit UIntPtr(ulong) | yang tidak dicentang | Tidak melempar ketika luapan | Dapat melemparkan dalam konteks 32-bit | (UIntPtr)uLongVariable |
| explicit operator uint(UIntPtr) | yang tidak dicentang | Tidak melempar ketika luapan | Dapat melemparkan dalam konteks 64-bit | (uint)uintPtrVariable |
Cara memperbaiki pelanggaran
Periksa kode Anda untuk menentukan apakah ekspresi yang ditandai dapat menyebabkan perubahan perilaku, dan pilih cara yang sesuai untuk memperbaiki diagnostik dari opsi berikut:
Opsi perbaikan:
- Jika ekspresi tidak akan menyebabkan perubahan perilaku:
- Jika jenis
IntPtratauUIntPtrdigunakan sebagai jenis bawaanintatauuint, ubah jenis menjadinintataunuint. - Jika jenis
IntPtratauUIntPtrdigunakan sebagai pointer asli, ubah jenis ke tipe pointer asli yang sesuai. - Jika Anda tidak dapat mengubah jenis variabel, abaikan peringatannya.
- Jika jenis
- Jika ekspresi dapat menyebabkan perubahan perilaku, bungkus dengan pernyataan
checkedatauuncheckeduntuk mempertahankan perilaku sebelumnya.
Contoh
Pelanggaran:
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.
}
}
Perbaikan:
- Jika ekspresi tidak akan menyebabkan perubahan perilaku dan jenis
IntPtratauUIntPtrdigunakan sebagai tipe asliintatauuint, ubah jenis menjadinintataunuint.
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;
}
}
- Jika ekspresi dapat menyebabkan perubahan perilaku, bungkus ekspresi tersebut dengan pernyataan
checkedatauuncheckeduntuk mempertahankan perilaku sebelumnya.
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);
}
}
Kapan harus menekan peringatan
Jika ekspresi tidak akan menyebabkan perubahan perilaku, aman untuk menekan peringatan dari aturan ini.