"delegate {}"匹配"Func <int,int,..>"?

Roy*_*mir 2 .net c# generics .net-4.0

我在这里读Jon Skeet的答案

他的一个样本是:

  static void Main()
    {
        int x = 0;
        Foo( delegate { return x; } );
    }

    static void Foo(Func<int, int> action)
    {
        Console.WriteLine("I suspect the anonymous method...");
    }
Run Code Online (Sandbox Code Playgroud)

但是如何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;
}
Run Code Online (Sandbox Code Playgroud)

我想使用通用处理程序,所以:

class MyClass
{
    public  Action<object> MyEventHandler;
    public  event MyEventHandler MyEvent;
}
Run Code Online (Sandbox Code Playgroud)

但我得到这个错误:

'UserQuery.MyClass.MyEventHandler(object)'是'方法',但用作'类型'

为什么不承认呢?

cdh*_*wie 8

第一个问题的答案是代理的参数是由编译器推断的.编译一个匿名方法,该方法将一个int参数作为参数,并且根本不做任何操作.代码可能是这样编写的:

Foo( delegate (int dummy) { return x; } );
Run Code Online (Sandbox Code Playgroud)

通过省略参数列表,您告诉编译器发出一个方法,该方法与当前上下文中的委托类型具有相同的参数类型.编译器知道a Func<int, int>是预期的,因此它能够使匿名方法的参数类型匹配.

换句话说,delegate { ... }告诉编译器"创建一个匿名方法,但我不关心参数是什么,因为我不会使用它们,所以发出任何参数将允许此委托在此上下文中被接受." (这与delegate () { ... }"创建一个带零参数的匿名方法" 不同.请注意括号.如果将这些括号添加到示例代码中,它确实无法编译.)

在第二种情况下,您使用的是字段名称,其中包含类型名称.定义字段不会创建具有字段名称的类型.你的第一个例子是正确的; 在这种情况下,MyEventHandler是一个类型,而不是一个字段.(即使它确实有效,使用泛型也不会有用,因为最终的委托签名已在编译时确定.使用泛型不会带来任何净优势.)