允许多个系统显式转换器,但不允许多个用户显式转换器。为什么?

时间:2013-05-10 12:44:48

标签: c# operators operator-overloading explicit explicit-conversion

如果我有这个代码,这将编译并按原样运行:

class MyNumber // Just a class.
{
    static public explicit operator MyNumber(byte b)
    {
        return new MyNumber();
    }
}

Decimal d = new Decimal();
MyNumber c1 = (MyNumber)d;

Perhapse有些人有点意外,因为从decimalMyNumber没有明确的演员。但是由于存在从decimalbyte的显式转换,并且还存在从byteMyNumber的显式转换,编译器非常友好地插入该额外显式为我而演。

简而言之:如果程序员使用显式转换,编译器可以自由地搜索其他显式转换以使整个过程完成。

所以......我在自己的课上尝试过同样的事情。我使用了bytedecimal,而不是MyByteMydecimal。代码如下所示:

class MyDecimal // Simulates a decimal.
{
    static public explicit operator MyByte(MyDecimal a) // Just like in a decimal.
    {
        return new MyByte();
    }
}

class MyByte // Simulates a byte.
{
}

class MyNumber // Just a class.
{
    static public explicit operator MyNumber(MyByte b)
    {
        return new MyNumber();
    }
}

MyDecimal d = new MyDecimal();
MyNumber c2 = (MyNumber)d; // <== Will not compile!

最后一行不会编译。它给出了错误:“无法将类型'DoubleExplicitCasts.Program.MyDecimal'转换为'DoubleExplicitCasts.Program.MyNumber'”。嗯......为什么不呢???

所以我的问题是:为什么.NET系统中的显式运算符得到特殊处理而我的用户显式运算符没有?

修改
我知道这段代码不起作用,并且值不会从一个实例转移到另一个实例,但这不是重点。

2 个答案:

答案 0 :(得分:2)

嗯,琐碎,因为它是由C#标准定义的。

从第6.4.3节开始:

  
    

评估用户定义的转化从不涉及多个用户定义或提升的转换运算符。换句话说,从类型S到类型T的转换将永远不会首先执行从S到X的用户定义转换,然后执行从X到T的用户定义转换。

  

至于为什么他们选择以这种方式限制转换 - 这是另一回事。我将提出两个可能的原因:

  1. 这将允许太多“令人惊讶的”转换的可能性
  2. 这会使编译过程太慢(可能是组合爆炸)
  3. 但这只是我的推测。

答案 1 :(得分:2)

IMO,这将导致“快乐调试”,真正,非常复杂和非显而易见的代码。

想象一下这样的用户定义转换的3个或更多级别,以及如何搜索由中间转换引起的错误(例如,这种转换是错误引入的,或者不应该在那种情况下使用)。 / p>

感谢上帝不支持这种行为。