为什么编译器必须知道一个 lambda 的类型?

Why does the compiler have to know the type of one lambda?

这段代码不容易阅读,很抱歉,但出于我的兴趣,为什么编译器必须知道 lambda 的类型。让我们看看代码,别担心,这不是真正的代码。

bool b1 = true, b2, b3;
Action action = () => Console.WriteLine("Hello");
(b1 ? () => 
  {
    b2 = true;
    b3 = false;
  } : action)();

行得通。但是...

为什么我不能这样做?

bool b1 = true, b2, b3;
(b1 ? () => 
  {
    b2 = true;
    b3 = false;
  } : () => Console.WriteLine("Hello"))();

能否请您解释一下,在哪些情况下编译器必须知道函数的显式类型(在本例中 Action)?

VS2017 告诉我....

CS0173 Type of conditional expression cannot be determined because there is no implicit conversion between 'lambda expression' and 'lambda expression'

因为 .NET 中没有委托等价:您可以有两个具有相同签名的委托,例如

delegate void MyDelegate1()

delegate void MyDelegate2()

但是您不能将一个代表分配给另一个……您不能:

MyDelegate1 del1 = null;
MyDelegate2 del2 = del1;

它们是截然不同且不兼容的委托类型。它们仅从 "human" 的角度来看是 "similar",而不是从 compiler/of .NET 的角度来看。

很明显,如果委托的确切 "type"(不仅是其签名)在 .NET 中很重要,那么 .NET 就不能 "desume"。在您的第一个示例中,编译器可以看到委托类型是 Action,因此它可以推断出 () => { ... } 是一个 Action。在第二个例子中,编译器没有这个 "hint".