Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overloading the + operator so it is sensitive to being called in a checked or unchecked context

UPDATE: I've found the answer, which I will post in a couple of days if nobody else does.


I am creating a numeric struct, so I am overloading the arithmetical operators. Here is an example for a struct that represents a 4-bit unsigned integer:

public struct UInt4
{
    private readonly byte _value;

    private const byte MinValue = 0;
    private const byte MaxValue = 15;

    public UInt4(int value)
    {
        if (value < MinValue || value > MaxValue)
            throw new ArgumentOutOfRangeException("value");

        _value = (byte) value;
    }

    public static UInt4 operator +(UInt4 a, UInt4 b)
    {
        return new UInt4((a._value + b._value) & MaxValue);
    }
}

The overloaded addition operator allows this code:

var x = new UInt4(10);
var y = new UInt4(11);
var z = x + y;

Here, the calculation overflows, so the variable z has the value 5. I would also like to be able to do this, however:

var x = new UInt4(10);
var y = new UInt4(11);
var z = checked ( x + y );

This sample should throw an OverflowException. How can I achieve that?

I have already established that the checked context does not extend to called methods, so, for example, this does not throw, regardless of whether it is called in a checked or unchecked context:

public static UInt4 operator +(UInt4 a, UInt4 b)
{
    int i = int.MaxValue;

    //this should throw in a checked context, but when
    //the operator is used in a checked context, this statement
    //is nonetheless unchecked.
    byte b = (byte)i;

    return new UInt4((a._value + b._value) & MaxValue);
}

Is there a way of declaring two overloads of the addition operator, one checked and the other unchecked? Alternatively, is there a way to determine at run time the context of the caller (which seems highly unlikely, but I thought I'd ask nonetheless), something like this:

public static UInt4 operator +(UInt4 a, UInt4 b)
{
    byte result = (byte)(a._value + b._value);

    if (result > MaxValue)
        if (ContextIsChecked())
            throw new OverflowException();
        else
            result &= MaxValue;
     return new UInt4(result);
}

private static bool ContextIsChecked()
{
    throw new NotImplementedException("Please help.");
}
like image 403
phoog Avatar asked Mar 15 '13 23:03

phoog


1 Answers

According to MSDN, the checked and unchecked keywords only apply to the integral types. Therfore, you cannot create your own types that can make use of the checked and unchecked keywords.

like image 138
Jacob VanScoy Avatar answered Nov 13 '22 01:11

Jacob VanScoy