C#语言设计:“is”操作符中的方法组

C#语言设计:“is”操作符中的方法组,c#,language-design,method-group,C#,Language Design,Method Group,我对C语言的一些设计选择很感兴趣。 C#规范中有一条规则,允许将方法组用作is运算符的表达式: class Foo { static void Main() { if (Main is Foo) Main(); } } 上述条件总是错误的,如规范所述: 7.10.10是操作员 •如果E是方法组或空文本,如果E的类型是引用类型 或可为null的类型,且E的值为null,则结果为false 我的问题:在类似于的“运行时”操作符中,允许在类似CLR的方法组中使用没有运行时表示的C#languag

我对C语言的一些设计选择很感兴趣。 C#规范中有一条规则,允许将方法组用作
is
运算符的表达式:

class Foo {
  static void Main() { if (Main is Foo) Main(); }
}
上述条件总是错误的,如规范所述:

7.10.10是操作员

•如果E是方法组或空文本,如果E的类型是引用类型 或可为null的类型,且E的值为null,则结果为false


我的问题:在类似于
的“运行时”操作符中,允许在类似CLR的方法组中使用没有运行时表示的C#language元素的目的/要点/原因是什么

is操作员
用于检查
对象的运行时类型是否为
与给定类型兼容

示例

public static void Test (object o) 
{
   Class1 a;

   if (o is Class1) {}
}

如果满足以下两个条件,则is表达式的计算结果为true:

  • 表达式不为空
  • 表达式可以强制转换为类型。也就是说,表单(类型)(表达式)的强制转换表达式将在不引发异常的情况下完成。有关详细信息,请参见7.6.6强制转换表达式
所以你的例子在第二点上是假的,它必须是可浇铸的特定类型

我希望我没有误解这个问题

允许在类似“运行时”操作符的类CLR方法组中使用不带运行时表示的C#语言元素的目的/要点/原因是什么

语言设计笔记档案没有提到为什么做出这个决定,所以对答案的任何猜测都只是猜测。他们确实提到,如果“是”的结果可以静态地确定为总是正确的或错误的,那么它应该如此确定并产生警告。这可能只是一个错误,这似乎是有道理的

将错误转化为警告(或简单地允许错误)的最常见原因是,这样可以减轻自动生成代码的程序生产者的负担。然而,我没有看到一个真正引人注目的场景

更新:

我刚刚检查了C#1.0规范。它没有这种语言。它没有说任何关于null或方法组参数的内容。当然,它没有提到方法组转换,因为在C#1.0中没有隐式的方法组转换;如果要将方法M转换为委托类型D,则必须显式调用“newd(M)”

后一点是“M是D”返回false而不是true的理由;你不能合法地说“D=M”;那么为什么“M是D”应该是真的呢

当然,在C#2.0中,这没有什么意义,因为在C#2.0中可以说“dd=M”

我还问了一位在场的人,“is”操作符是什么时候设计的,他不记得曾经以这种或那种方式决定过这个问题。他怀疑“is”操作符的最初设计是不给出任何错误,只给出警告,规范中所有关于如何处理方法组、空值等的文本都是在C#2.0版本规范的后期添加的,并且基于编译器的实际操作

简而言之,这看起来像是C#1.0中的一个设计漏洞,当规范更新为C#2.0时,它被掩盖了。看起来,这种特定的行为并不是我们想要的,也不是故意实施的

匿名方法在C#2.0中用作“is”的参数时确实会产生错误,这一事实强化了这一理论。这样做并不是一个突破性的改变,但使“M is D”突然开始返回真值或成为错误将是一个突破性的改变

进一步更新:


在调查这件事的过程中,我学到了一些有趣的东西。(对我来说)当特性最初设计时,设计是允许类型的名称或类型对象作为“is”的右参数。然而,早在C#1.0发布之前,这个想法就被抛弃了。

这是。。。惊人的
as
操作符的部分没有提到方法组。@蒂姆:但是“as”操作符被定义为强制转换、条件操作符和“is”操作符组合的语法糖,因此“as”操作符不需要提到方法组。因此
Main as Foo
总是
null
。而且
Main-as-System.Action
也是
null
,而
System.Action a=Main
是可以的。顺便说一句,@TimRobinson(C#5编译器)
Main-as-Action
给出了,所以不,它不是
null
。问题是,为什么
Main不是Class1
编译器错误?@SLacks:也许我们应该使用反射器来进一步调查这个问题。@SLaks,使用整形器,我得到一个警告,提示:“给定的表达式从未提供过类型”。现在检查反射器。@Filip:同意。我在命令行得到警告,cf:@Andreas,对。它采用“引用类型”,方法可以是委托,因此这不会给您带来编译时错误。这是我的猜测。