为什么方法组允许在'is'运算符的左侧,如何在实践中使用它?

Nic*_*Eye 8 c# methods delegates

首先,"方法组是由成员查找产生的一组重载方法".在我的例子中,我使用了Console.WriteLine19个重载的方法集.

C#语言规范中方法组的定义还指出:"在调用表达式(第7.6.5节)中允许使用方法组,在委托创建表达式(第7.6.10.5节)中使用方法组,并在左侧使用是一个运算符,可以隐式转换为兼容的委托类型(第6.6节)."

我可以想到这个功能可能有用的一个场景:

Action<string> print = (Action<string>)Console.WriteLine;
print("Hello!");

if (Console.WriteLine is Action<string>) 
{
    Console.WriteLine("We're compatible!");
}
Run Code Online (Sandbox Code Playgroud)

前几行显示我们可以将方法组" Console.WriteLine转换"为委托.实际发生的是"转换为兼容委托类型的隐式转换",它创建委托实例,调用Console.WriteLine具有兼容签名的许多重载方法之一.

因此,根据规范,我们可以使用上面提到的"运算符的左侧"功能来测试方法组是否与给定的委托类型兼容(存在隐式转换).这是在示例代码中的'if'语句中检查的内容.

令人惊讶的是,代码编译,但发出警告"给定的表达式永远不会提供('System.Action')类型".因此,似乎不会尝试在运行时检查方法组和委托类型的兼容性.

因此,我的问题:

  • 如果在运行时无法执行检查,为什么在'is'运算符的左侧允许方法组?
  • 为什么这个构造会发出警告而不是编译错误?
  • 是否有任何在'is'运算符左侧使用方法组的实际场景?
  • 这是为未来的用途保留的东西,即设想上面的代码将在某一天工作吗?

the*_*heB 1

规范 (4.0) 明确指出了这种特定情况:

\n
\n

7.10.10is操作员

\n

[...] 运算的结果E is T,其中E是表达式,T是类型,是布尔值 [...]

\n
\n

到目前为止,一切都很好。规范继续:

\n
\n

如果E是方法组[...],则结果为 false。

\n
\n

有了这些信息,让我们看看您的问题。

\n
\n

如果无法在运行时执行检查,为什么 \xe2\x80\x98is\xe2\x80\x99 运算符的左侧允许使用方法组?

\n
\n

该规范允许进行此操作。请参阅利珀特在另一个问题上的回答,了解这是如何发生的。

\n
\n

为什么这个构造会给出警告而不是编译错误?

\n
\n

该构造在语法上是有效的,即使它总是评估为 false。该警告只是让您知道您可能正在做一些意想不到的事情。

\n
\n

是否有在 \xe2\x80\x98is\xe2\x80\x99 运算符左侧使用方法组的实际场景?

\n
\n

可能不会。也许如果你传递了一个object可能是方法组或者可能是其他东西的东西,那么这个构造可能会很有用。(诚​​然,这是一个人为的例子,代表了一些严重可疑的做法。)

\n
\n

这是为将来使用保留的东西吗,即设想上面的代码有一天会起作用?

\n
\n

不。再次引用 Lippert 的话“如果‘M is D’突然开始返回 true 或成为错误,这将是一个重大改变。” [原文强调]

\n