C#语言设计:在`is`运算符内部使用方法组

28

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

class Foo {
  static void Main() { if (Main is Foo) Main(); }
}

根据规范所述,上述条件始终为false:

7.10.10 is运算符

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

我的问题:允许在类似于is这样的“运行时”运算符中使用没有CLR运行时表示的C#语言元素(例如方法组),这样做的目的/重点/原因是什么?


太惊人了。关于 as 运算符的部分没有提到方法组。 - Tim Robinson
@Tim:但是,“as”运算符被定义为一种语法糖,用于组合强制转换、条件运算符和“is”运算符,因此“as”运算符不需要提及方法组。 - Eric Lippert
1
所以 Main as Foo 总是 null。而 Main as System.Action 也是 null,然而 System.Action a = Main 是可以的。 - Tim Robinson
2个回答

21
允许在CLR中没有运行时表示的C#语言元素(例如方法组)与“is”等“运行时”操作符一起使用的目的/点/原因是什么?
语言设计笔记档案没有提到为什么要做出这个决定,所以任何答案都只能是猜测。它们确实提到,如果“is”的结果可以静态确定始终为true或false,则应如此确定并产生警告。这似乎可能只是一个错误。
将本来应该是错误变成警告(或简单地允许它)最常见的原因是减轻自动生成代码程序的制造者的负担。但是,我在这里看不到真正引人注目的情景。
更新:
我刚刚查看了C#1.0规范。它没有这种语言。它没有关于null或方法组参数的任何说明。当然,它也没有关于方法组转换的说明,因为在C#1.0中没有隐式方法组转换;如果您想要将方法M转换为委托类型D,必须明确调用“new D(M)” 。
后一点是“M is D”返回false而不是true的理由。您不能合法地说“D d = M;”,那么为什么“M is D”应该为true呢?
当然,在C#2.0中,这就不那么有意义了,因为您可以说“D d = M;”。
我还刚刚问过其中一位参与“is”操作符设计的人,他没有记忆中决定这个问题的方式。他怀疑“is”操作符的最初设计是不给出任何错误,仅给出警告,并且规范中关于如何处理方法组和null等内容的所有文本都是事后添加的,基于编译器实际执行的操作,用于C# 2.0版本的规范。简而言之,这似乎是C# 1.0中一个设计漏洞,当规范更新为C# 2.0时被掩盖了。看起来这种特定的行为并不是被期望和故意实现的。
事实上,这个理论得到了加强,因为在C# 2.0中,当匿名方法用作"is"的参数时会产生错误。这样做不会造成破坏性的改变,但“M is D”突然返回true或产生错误会造成破坏性的改变。
进一步更新:
在调查时,我了解到了一些有趣的事情(对我而言)。当最初设计该功能时,设计是允许类型名称或Type对象作为“is”的右侧参数。然而,在C# 1.0发布之前,这个想法就被放弃了。

3

首先,方法不是一种类型,msdn清楚地说明了以下内容:

is运算符用于检查对象的运行时类型是否与给定类型兼容。

示例

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

   if (o is Class1) {}
}

来自MSDN:

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

  • expression不为null。
  • expression可以转换为type类型。也就是说,形如(type)(expression)的转换表达式将成功完成而不会抛出异常。更多信息请参见7.6.6 转换表达式。

因此,你的示例返回false是因为它不能转换为特定类型。

希望我没有误解问题。


1
问题是,为什么“Main is Class1”不是编译器错误? - SLaks
@SLaks,是的,那是因为方法不是类型。 :) - Filip Ekberg
@Filip: 错了。方法组、匿名委托和lambda表达式都是无类型的表达式,这意味着它们表示没有内在类型的值。(除非在委托上下文中使用,此时它会成为委托的类型)这就是为什么 var a = 1 是有效的,而 var a = Console.WriteLine 是无效的原因。 - SLaks
@SLaks,这就是我刚才说的,方法不是类型。 - Filip Ekberg
@Filip:正则表达式也不是类型,但"abc"是一个已分类的表达式,属于String类型。 - SLaks
显示剩余9条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接