重载+运算符,以便在已检查或未检查的上下文中调用它

pho*_*oog 7 c# operator-overloading unchecked

更新:我找到了答案,如果没有其他人的话,我会在几天后发布.


我正在创建一个数字结构,所以我正在重载算术运算符.以下是表示4位无符号整数的结构的示例:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

重载加法运算符允许此代码:

var x = new UInt4(10);
var y = new UInt4(11);
var z = x + y;
Run Code Online (Sandbox Code Playgroud)

这里,计算溢出,因此变量z具有该值5.我也希望能够做到这一点,但是:

var x = new UInt4(10);
var y = new UInt4(11);
var z = checked ( x + y );
Run Code Online (Sandbox Code Playgroud)

此示例应抛出OverflowException.我怎样才能做到这一点?

我已经确定已检查的上下文不会扩展到被调用的方法,因此,例如,无论是否在已检查或未检查的上下文中调用它,它都不会抛出:

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);
}
Run Code Online (Sandbox Code Playgroud)

有没有办法声明加法运算符的两个重载,一个被检查而另一个未经检查?或者,有没有办法在运行时确定调用者的上下文(这似乎不太可能,但我想我仍然会问),这样的事情:

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.");
}
Run Code Online (Sandbox Code Playgroud)

Jac*_*coy 3

根据 MSDNcheckedandunchecked关键字仅适用于整型。因此,您无法创建自己的可以使用选中和未选中关键字的类型。

更新

从 C# 11(.Net 7 的一部分)开始,用户类型可以定义自定义检查运算符

public record struct Point(int X, int Y)
{
    public static Point operator checked +(Point left, Point right)
    {
        checked
        {
            return new Point(left.X + right.X, left.Y + right.Y);
        }
    }
    
    public static Point operator +(Point left, Point right)
    {
        return new Point(left.X + right.X, left.Y + right.Y);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @JohnSaunders 如果我们为了论证而假设大象可以飞,我们就不能推断出我们假设的世界中的大象不是大象,因为现实世界中真正的大象不能飞。同样,如果有人问你“这辆 10 路公交车能带我去市政厅吗?” 回答“不”比说“如果那辆公共汽车存在,它就不会是这辆10号公共汽车”更有帮助。在 2003 年,我可能会询问在可验证代码中使用 `sizeof(int)`,而您可能会说“您建议的语言不是 C#”。但现在我们*可以*做到这一点——这是否意味着 C# 5 不是 C#? (2认同)