隐式和显式委托创建之间的区别(有和没有泛型)

Nat*_*ley 5 .net c# generics delegates .net-2.0

请参阅下面的Go()方法中的四行:

delegate void Action<T>(T arg);
delegate void Action();

void DoSomething<T>(Action<T> action)
{
    //...
}

void DoSomething(Action action)
{
    //...
}

void MyAction<T>(T arg)
{
    //...
}

void MyAction()
{
    //...
}

void Go<T>()
{
    DoSomething<T>(MyAction<T>); // throws compiler error - why?
    DoSomething(new Action<T>(MyAction<T>)); // no problems here
    DoSomething(MyAction); // what's the difference between this...
    DoSomething(new Action(MyAction)); // ... and this?
}
Run Code Online (Sandbox Code Playgroud)

请注意,第一次调用生成的编译器错误是: 方法"Action(T)"的类型参数无法从用法中推断出来.尝试显式指定类型参数.

Jon*_*eet 14

除了前者之外没有区别MyActionnew Action(MyAction)(当它们都有效时)在C#1中不起作用.这是一个implicit method group conversion.有时候这是不适用的,最值得注意的是当编译器无法确定你想要什么样的委托时,例如

Delegate foo = new Action(MyAction); // Fine
Delegate bar = MyAction; // Nope, can't tell target type
Run Code Online (Sandbox Code Playgroud)

这在您的问题中发挥作用,因为所涉及的两个方法都是重载的.这基本上导致了头痛.

至于泛型方面 - 它很有趣.方法组并没有从C#3类型推断中得到太多的喜爱 - 我不确定它是否会在C#4中得到改进.如果您调用泛型方法并指定类型参数,则类型推断可以很好地工作 - 但如果您尝试以相反的方式执行此操作,则会失败:

using System;

class Test
{
    static void Main()
    {
        // Valid - it infers Foo<int>
        DoSomething<int>(Foo);
        // Valid - both are specified
        DoSomething<int>(Foo<int>);
        // Invalid - type inference fails
        DoSomething(Foo<int>);
        // Invalid - mismatched types, basically
        DoSomething<int>(Foo<string>);
    }

    static void Foo<T>(T input)
    {
    }

    static void DoSomething<T>(Action<T> action)
    {
        Console.WriteLine(typeof(T));
    }
}
Run Code Online (Sandbox Code Playgroud)

C#3中的类型推断非常复杂,并且在大多数情况下运行良好(特别是它对LINQ很有用)但在其他一些情况下失败.在理想的世界中,在未来的版本中它会变得更容易理解更强大......我们会看到!