C# 重载+;运算符,因此它对在选中或未选中的上下文中被调用很敏感

C# 重载+;运算符,因此它对在选中或未选中的上下文中被调用很敏感,c#,operator-overloading,unchecked,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) { i

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


我正在创建一个数字结构,因此我正在重载算术运算符。以下是表示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);
    }
}
这里,计算溢出,因此变量z的值为
5
。然而,我也希望能够做到这一点:

var x = new UInt4(10);
var y = new UInt4(11);
var z = checked ( x + y );
此示例应抛出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);
}
有没有办法声明加法运算符的两个重载,一个是选中的,另一个是未选中的?或者,是否有一种方法可以在运行时确定调用方的上下文(这似乎不太可能,但我想我还是会问),如下所示:

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.");
}

,选中的
未选中的
关键字仅适用于。因此,您不能创建自己的类型来使用选中和未选中的关键字。

Close,so+1,但我不会接受这个答案,因为第一页上没有指定“内置整数类型”。我试图定义自己的整型,这就是为什么我希望它对选中/未选中的上下文敏感。换句话说,在第一页应该有一个指向内置整型文档的显式链接,但是没有,所以我觉得这个页面不明确。我找到了一个明确的来源,我会接受第一个引用它的答案。我想我明白了。这是因为您没有重写隐式转换运算符,并允许它转换为一种内置的整数类型,如。尽管我在MSDN上找不到明确的说明,但我猜这与Eric Lippert在文章底部解释的switch语句的工作原理类似。哦,不,根本不是这样。正确答案是“您不能创建自己的类型…”。考虑一下:如果我创建了一个到内置整数类型的隐式转换运算符,我将根据内置整数类型的范围(而不是我试图定义的类型的范围)进行溢出检查。您链接到的SO线程中的示例在未经检查的上下文中溢出时不会翻滚。或者更确切地说,它在未经检查的上下文中转换时不会表现出应有的行为,因为在未经检查的上下文中不可能抛出异常。@JohnSaunders如果为了论证起见,我们假设大象可以飞行,我们无法推断我们假想世界中的大象不是大象,因为现实世界中的大象不会飞。同样,如果有人问你“这辆10号巴士能带我去市政厅吗?”回答“不”比回答“如果那辆巴士存在,它就不会是这辆10号巴士”更有帮助。2003年,我可能会问在可验证代码中使用
sizeof(int)
,你会说“你建议的语言不是C”。但现在我们可以这样做了——这是否意味着C#5不是C#?这里有一个答案说这或多或少是不可能的。。。等着看你的方法…@AlexeiLevenkov我找到的答案也表明这是不可能的。我想到的一种方法是定义
UInt4Checked
UInt4Unchecked
类型,并在它们之间进行显式转换。Downvoter,请解释一下。投票结束不是一个真正的问题。你显然是为了说明问题,而不是为了找到答案。找一个博客。@Guffa事实上,我发布这个问题是为了找到答案,然后在发布15分钟后,我对在哪里寻找答案有了另一个想法,我找到了答案。不管怎样,stackoverflow鼓励人们发布他们已经知道答案的问题(尽管这里没有发生这种情况),并自己回答。看见
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.");
}