4

如果我有此代码,它将按应有的方式编译和工作:

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

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

也许有些人有点惊讶,因为从 adecimal到没有现成的显式转换MyNumber。但是由于有一个从decimalto的显式转换byte,也有一个从 a 的显式byte转换MyNumber,所以编译器很友好地为我插入了那个额外的显式转换。

简而言之:如果程序员使用显式转换,编译器可以自由搜索其他显式转换以使整个事情顺利进行。

所以......我在自己的课程中尝试了同样的事情。而不是byteand decimal,我使用MyByteand Mydecimal。代码如下所示:

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 系统中的显式运算符得到特殊处理而我的用户显式运算符没有?

编辑
我知道这段代码不起作用,并且值不会从一个实例转移到另一个实例,但这无关紧要。

4

2 回答 2

2

IMO,这将导致“愉快的调试”以及非常非常复杂且不明显的代码。

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

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

于 2013-05-10T12:55:45.527 回答
2

好吧,微不足道,因为这就是 C# 标准的定义方式。

从第 6.4.3 节开始:

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

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

  1. 这将允许太多“令人惊讶”的转换的可能性
  2. 它会使编译过程太慢(可能组合爆炸)

但这只是我的猜测。

于 2013-05-10T12:49:35.530 回答