我正在阅读Jon Skeet的回答here
他的一个样本是:
static void Main()
{
int x = 0;
Foo( delegate { return x; } );
}
static void Foo(Func<int, int> action)
{
Console.WriteLine("I suspect the anonymous method...");
}
但是Foo(Func<int, int>)
如何处理delegate { return x; }
Func<int>
?
事实上,Func< int,int,int,int,...>
也可以处理delegate { return x; }
...
问题1 对此行为有任何解释吗?
问题2
我有这段代码:
class MyClass
{
public delegate void MyEventHandler(object sender);
public event MyEventHandler MyEvent;
}
我想使用通用处理程序:
class MyClass
{
public Action<object> MyEventHandler;
public event MyEventHandler MyEvent;
}
但是我收到了这个错误:
'UserQuery.MyClass.MyEventHandler(object)'是'方法',但用作'类型'
为什么不识别它?
答案 0 :(得分:8)
第一个问题的答案是代理的参数是由编译器推断的。编译一个匿名方法,该方法将int
作为参数,并且不执行任何操作。代码可以这样写:
Foo( delegate (int dummy) { return x; } );
通过省略参数列表,您告诉编译器发出一个方法,该方法与当前上下文中的委托类型具有相同的参数类型。编译器知道期望Func<int, int>
,因此它能够使匿名方法的参数类型匹配。
换句话说,delegate { ... }
告诉编译器“创建一个匿名方法,但我不关心参数是什么,因为我不打算使用它们,所以发出任何参数将允许这个委托在这种情况下是可以接受的。“ (这与delegate () { ... }
不同,这意味着“创建一个接受零参数的匿名方法。”注意括号。如果将这些括号添加到示例代码中,它确实无法编译。)
在第二种情况下,您使用的是需要类型名称的字段名称。定义字段不会创建具有字段名称的类型。你的第一个例子是正确的;在这种情况下,MyEventHandler
是一种类型,而不是一个字段。 (即使这确实有效,使用泛型也不会有用,因为最终的委托签名已在编译时确定。使用泛型不会带来任何净优势。)