A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca2020 below:

CA2020: Prevent behavioral change caused by built-in operators of IntPtr/UIntPtr - .NET

Property Value Rule ID CA2020 Title Prevent behavioral change caused by built-in operators of IntPtr/UIntPtr Category Reliability Fix is breaking or non-breaking Non-breaking Enabled by default in .NET 9 As suggestion Cause

This rule fires when it detects a behavioral change between .NET 6 and .NET 7 introduced by the new built-in operators of IntPtr and UIntPtr.

Rule description

With the numeric IntPtr feature, IntPtr and UIntPtr gained built-in operators for conversions, unary operations, and binary operations. These operators might throw when overflowing within checked context or may not throw in unchecked context compared to the previous user-defined operators in .NET 6 and earlier versions. You might encounter this behavioral change when upgrading to .NET 7.

List of APIs affected Operator Context In .NET 7 In .NET 6 and earlier Example operator +(IntPtr, int) checked Throws when overflows Doesn't throw when overflows checked(intPtrVariable + 2); operator -(IntPtr, int) checked Throws when overflows Doesn't throw when overflows checked(intPtrVariable - 2); explicit operator IntPtr(long) unchecked Doesn't throw when overflows Can throw in 32-bit contexts (IntPtr)longVariable; explicit operator void*(IntPtr) checked throws when overflows Doesn't throw when overflows checked((void*)intPtrVariable); explicit operator IntPtr(void*) checked throws when overflows Doesn't throw when overflows checked((IntPtr)voidPtrVariable); explicit operator int(IntPtr) unchecked Doesn't throw when overflows Can throw in 64-bit contexts (int)intPtrVariable; operator +(UIntPtr, int) checked Throws when overflows Doesn't throw when overflows checked(uintPtrVariable + 2); operator -(UIntPtr, int) checked Throws when overflows Doesn't throw when overflows checked(uintPtrVariable - 2); explicit operator UIntPtr(ulong) unchecked Doesn't throw when overflows Can throw in 32-bit contexts (UIntPtr)uLongVariable explicit operator uint(UIntPtr) unchecked Doesn't throw when overflows Can throw in 64-bit contexts (uint)uintPtrVariable How to fix violations

Examine your code to determine if the flagged expression could cause a behavioral change, and choose an appropriate way to fix the diagnostic from the following options:

Fix options:

Example

Violation:

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.
    }
}

Fix:

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;
    }
}
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);
    }
}
When to suppress warnings

If the expression would not cause a behavioral change, it's safe to suppress a warning from this rule.

See also

RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4