【发布时间】:2018-05-16 21:47:11
【问题描述】:
考虑一下这个小程序。
public class Program
{
public static void Main()
{
// the first path compiles
RunAction(() => { });
// the second path does not compile
RunDelegate(() => {});
}
private static void RunAction(Action run) => RunDelegate(run);
private static void RunDelegate(Delegate run) { }
}
第一个路径编译并暗示
-
() => {}lambda 是一个Action, -
Action是Delegate,并且 - 因此
() => {}lambda 是Delegate。
为什么第二个路径不编译?
通常编译器能够在步骤 (1) 和 (3) 之间进行跳跃。这是编译器通常如何处理这种嵌套的 is-a 关系的示例。
public class Program2
{
public static void Main()
{
// both of these comple
AcceptPerson(new Programmer());
AcceptAnimal(new Programmer());
}
private static void AcceptPerson(Person p) => AcceptAnimal(p);
private static void AcceptAnimal(Animal a) { }
}
public class Programmer : Person { }
public class Person : Animal { }
public class Animal { }
【问题讨论】:
-
不幸的是,当您将
Delegate作为一种类型处理时,编译器必须推断出一个 actual 委托类型以用于您的委托,并且可能有任何用于您的实际代码的可能委托类型的数量。编译器只是说“不,不能那样做”,因为这是语言设计者在这种情况下决定做的事情。 -
假设 (1.) 不正确。
() => {}不是Action没有Actionsomewhere 在代码中允许编译器进行推断的类型声明。 -
@spender 对。我现在记得
Action run = () => {};和RunAction(() => {});都将lambda 声明为Action。在第二种情况下,这不太直观。 -
具体来说,问题不在于编译器无法确定您正在处理
Delegate,问题在于编译器不了解您正在处理的具体委托with,它们都是派生自Delegate的实例。