Bagikan melalui


CA2020: Mencegah perubahan perilaku yang disebabkan oleh operator bawaan IntPtr/UIntPtr

Properti Nilai
ID Aturan CA2020
Judul Mencegah perubahan perilaku yang disebabkan oleh operator bawaan IntPtr/UIntPtr
Golongan Keandalan
Perbaikan bersifat disruptif atau non-disruptif Non-disruptif
Diaktifkan secara default di .NET 8 Sebagai saran

Penyebab

Aturan ini diaktifkan ketika mendeteksi perubahan perilaku antara .NET 6 dan .NET 7 yang diperkenalkan oleh operator bawaan baru dan IntPtrUIntPtr.

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) dicentang Melempar ketika luapan Tidak melempar ketika luapan checked(intPtrVariable - 2);
Operator eksplisit IntPtr(long) 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*) dicentang melempar ketika luapan Tidak melempar ketika luapan checked((IntPtr)voidPtrVariable);
int operator eksplisit(IntPtr) tidak dicentang Tidak melempar ketika luapan Dapat melemparkan 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);
UIntPtr(ulong) operator eksplisit tidak dicentang Tidak melempar ketika luapan Dapat melemparkan dalam konteks 32-bit (UIntPtr)uLongVariable
uint operator eksplisit(UIntPtr) 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:
    • IntPtr Jika jenis atau UIntPtr digunakan sebagai asli int atau uint, ubah jenis menjadi nint atau nuint.
    • IntPtr Jika jenis atau UIntPtr digunakan sebagai penunjuk asli, ubah jenis ke jenis penunjuk asli yang sesuai.
    • Jika Anda tidak dapat mengubah jenis variabel, tekan peringatan.
  • Jika ekspresi dapat menyebabkan perubahan perilaku, bungkus dengan checked pernyataan atau unchecked untuk 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 IntPtr jenis atau UIntPtr digunakan sebagai asli int atau uint, ubah jenis menjadi nint atau 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;
    }
}
  • Jika ekspresi dapat menyebabkan perubahan perilaku, bungkus dengan checked pernyataan atau unchecked untuk 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.

Baca juga