如果有的话,哪些与转化等同的情况是错误的?

时间:2016-12-19 17:22:36

标签: c# operator-overloading language-lawyer

请考虑以下事项:

using System;

struct FooEnum {
    public static implicit operator TypeCode(FooEnum foo) { return TypeCode.Empty; }
}

struct FooDelegate {
    public static implicit operator EventHandler(FooDelegate foo) { return null; }
}

struct FooInt {
    public static implicit operator int(FooInt foo) { return 0; }
}

class Foo {
    public static void Main(string[] args) {
        Console.WriteLine(new FooEnum() == new FooEnum());  // CS0019
        Console.WriteLine(new FooDelegate() == new FooDelegate());  // OK
        Console.WriteLine(new FooInt() == new FooInt());    // OK
    }
}

编译它会产生

  

错误CS0019:运算符'=='无法应用于'FooEnum'和'FooEnum'类型的操作数

使用VC#2005 8.0.50727.8745,csc 4.6.1586.0,Roslyn 1.3.2和Roslyn 2.0.0-rc2进行测试。结果在所有情况下都是一样的。

根据C# language specification 5.0,§7.10:

  

对于x op y形式的操作,其中op是a   比较运算符,重载决策(第7.3.4节)用于选择   特定的运营商实施。操作数转换为   所选运算符的参数类型以及结果的类型   是运算符的返回类型。

所有枚举类型(第7.10.5节),所有委托类型(第7.10.8节)和int(第7.10.1节)都存在预定义运算符。二元运算符重载决策(第7.3.4节)指定,因为Foo类型都没有定义自己的相等运算符,

  

...预定义的二元运算符 op 实现,包括它们的   提升形式,成为候选运营商的集合   操作。给定运算符的预定义实现是   在运营商的描述中指定(§7.8到§7.12)。   对于预定义的枚举和委托运算符,所考虑的唯一运算符是由枚举或委托类型定义的运算符,它们是其中一个操作数的绑定时类型。

(这里“绑定时间”表示编译时,因为不涉及dynamic个表达式。)

突出显示的句子似乎解释了为什么在选择重载时不考虑隐式转换为TypeCode(因此FooEnum案例无效的原因),但是,同样的道理,{ {1}}大小写应该无效,并且调用就好了。 (FooDelegate是一个无聊的案例,用于证明对预定义运算符的隐式转换被认为是。)

我是否正确阅读了规范,因为FooInt比较也应该产生错误?如果没有,通过什么顺序的规则是允许的(假设编译器是正确的)以及为什么该序列不允许FooDelegate(如果这不明显)?

0 个答案:

没有答案