Search code examples
c#.netinteger-arithmetic

Is it possible to detect at run-time the current unchecked/checked arithmetic context?


I could use something like this to check...

private static readonly int IntMaxValue = int.Parse(int.MaxValue.ToString());
private static bool IsChecked()
{
    try {
        var i = (IntMaxValue + 1);
        return false;
    }
    catch (OverflowException) {
        return true;
    }
}

... but that's a lot of overhead in a tight loop, throwing and catching just to detect it. Is there a lighter way to do this?

EDIT for more context...

struct NarrowChar
{
    private readonly Byte b;
    public static implicit operator NarrowChar(Char c) => new NarrowChar(c);
    public NarrowChar(Char c)
    {
        if (c > Byte.MaxValue)
            if (IsCheckedContext())
                throw new OverflowException();
            else
                b = 0; // since ideally I don't want to have a non-sensical value
        b = (Byte)c;
    }
}

If the answer is just 'no', don't be afraid to simply say that :)


Solution

  • So the answer seems to be 'no', but I figured out the solution for my particular problem. It could be useful to someone else who ends up in this situation.

    public NarrowChar(Char c) {
        var b = (Byte)c;
        this.b = (c & 255) != c ? (Byte)'?' : b;
    }
    

    First we "probe" the checked/unchecked context by just trying the cast. If we're checked, the overflow exception is thrown by the (Byte) c. If we're unchecked, the bit mask and comparison to c tells us if there was an overflow in the casting. In our particular case, we want the semantics of NarrowChar such that a Char that won't fit in a Byte gets set to ?; just like if you transcode a String of to ISO-8759-1 or ASCII you get ?.

    Doing the cast first is important to the semantics. Inlining b will break that "probing" behaviour.