【问题标题】:C# Language Design: method group inside `is` operatorC# 语言设计:`is` 运算符内的方法组
【发布时间】:2010-07-12 20:07:53
【问题描述】:

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

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

如规范所述,上述条件始终为假:

7.10.10 is 运算符

如果 E 是方法组或空字面量,of 如果 E 的类型是引用类型 或者一个可为空的类型并且E的值为null,结果为false。

我的问题: 允许在像 is 这样的“运行时”运算符内的方法组中使用没有运行时表示的 C# 语言元素的目的/要点/原因是什么?

【问题讨论】:

标签: c# language-design method-group


【解决方案1】:

允许在像 is 这样的“运行时”运算符中使用 CLR 中没有运行时表示的 C# 语言元素的目的/要点/原因是什么?

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

将可能正确的错误变成警告(或简单地允许它)的最常见原因是因为这减轻了自动生成代码的程序的生产者的负担。但是,我在这里没有看到真正令人信服的场景。

更新:

我刚刚检查了 C# 1.0 规范。它没有这种语言。它没有说明空值或方法组参数。当然,它没有说明方法组转换,因为在 C# 1.0 中没有隐式方法组转换;如果要将方法 M 转换为委托类型 D,则必须显式调用“new D(M)”。

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

当然,在 C# 2.0 中这不太有意义,因为您可以说“D d = M;”在 C# 2.0 中。

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

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

匿名方法在 C# 2.0 中用作“is”的参数时会产生错误,这一事实强化了这一理论。这样做不会是一个重大更改,但会是一个重大更改,让“M 是 D”突然开始返回 true 或成为错误。

进一步更新:

在调查这个问题时,我学到了一些有趣的东西。 (对我来说。)最初设计该功能时,设计是允许类型的名称,或 Type 对象作为“is”的右手参数。不过,在 C# 1.0 发布之前,这个想法就被放弃了。

【讨论】:

    【解决方案2】:

    首先方法不是类型,msdn明确声明如下:

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

    示例

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

    From MSDN:

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

    • 表达式不为空。
    • 表达式可以转换为类型。也就是说,(type)(expression) 形式的强制转换表达式将在不引发异常的情况下完成。有关详细信息,请参阅 7.6.6 转换表达式。

    因此,您的示例为错误的原因在于第二点,它必须可以转换为特定类型。

    希望我没有误会这个问题。

    【讨论】:

    • 问题是,为什么Main is Class1不是编译器错误?
    • @SLacks:也许我们应该使用 Reflector 来进一步调查。
    • @SLaks,使用 ReShaper 我收到一条警告消息:“给定的表达式从未提供类型”。现在用反射器检查..
    • @Filip:同意。我在命令行收到警告,参见:msdn.microsoft.com/en-us/library/230kb9yt%28VS.90%29.aspx
    • @Andreas,对。它需要一个“引用类型”,一个方法可以是一个委托,因此这不会给你一个编译时错误。反正这是我的猜测。
    猜你喜欢
    • 2014-05-22
    • 2017-08-04
    • 1970-01-01
    • 2021-08-03
    • 2022-11-03
    • 2012-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多