我对C#语言的一些设计选择感兴趣。
C#规范中有一条规则允许使用方法组作为is
运算符的表达式:
class Foo {
static void Main() { if (Main is Foo) Main(); }
}
上述条件总是假的,正如规范所说:
7.10.10是运算符
•如果E是方法组或空文字,则E的类型是引用类型 或者是可以为null的类型,并且E的值为null,结果为false。
我的问题:允许在CLR中使用没有运行时表示的C#语言元素的目的/要点/原因是什么,例如像{{1}这样的“运行时”运算符中的方法组}?
答案 0 :(得分:21)
允许在CLR中使用没有运行时表示的C#语言元素的目的/点/原因是什么,就像这样的“运行时”运算符中的方法组一样?
语言设计说明档案没有提到为什么做出这个决定,所以对答案的任何猜测都是猜想。他们确实提到如果“是”的结果可以被静态地确定为永远是真或假,那么它就是如此确定并产生警告。似乎这可能只是一个错误似乎是合理的。
将可能正确的错误转换为警告(或简单地允许它)的最常见原因是因为这减轻了自动生成代码的程序的生产者的负担。但是,我在这里看不到一个非常引人注目的场景。
更新:
我刚检查了C#1.0规范。它没有这种语言。它没有说明null或方法组参数。当然,它没有说明方法组转换,因为在C#1.0中没有隐含的方法组转换;如果要将方法M转换为委托类型D,则必须显式调用“new D(M)”。
后一点是“M是D”返回虚假而非真实的理由;你不能合法地说“D d = M;”那么为什么“M是D”是真的呢?
当然在C#2.0中这没有多大意义,因为你可以说“D d = M;”在C#2.0中。
我还问过“是”操作员设计时出现的其中一个人,并且他无法以某种方式决定这个问题。他的怀疑是“is”操作符的原始设计是不给出任何错误,只是警告,并且规范中的所有文本关于如何处理方法组和空值以及事后添加的内容, C#2.0版本的规范,并基于编译器实际执行的操作。
简而言之,看起来这是C#1.0中的一个设计漏洞,当为C#2.0更新规范时,它已被涂抹。看起来并不是这种特定的行为,而是故意实施的。
当在C#2.0中用作“is”的参数时,匿名方法做会产生错误这一事实加强了这一理论。这样做不会是一个突破性的变化,但它会是一个突破性的变化,使“M is D”突然开始返回true或者是一个错误。
进一步更新:
在研究这个时,我学到了一些有趣的东西。 (对我来说。)当最初设计该功能时,设计是允许类型名称或Type对象作为“is”的右手参数。在C#1.0出货之前,这个想法就被放弃了。
答案 1 :(得分:3)
首先,一个方法不是一个类型,msdn明确说明如下:
用于检查的运算符
is
是否为对象的运行时类型 与给定类型兼容
示例强>
public static void Test (object o)
{
Class1 a;
if (o is Class1) {}
}
如果满足以下两个条件,则表达式的计算结果为true:
因此,你的例子出现错误的原因在于第二点,它必须可以转换为特定类型。
我希望我没有错过理解这个问题。