隐性和显性委托创作之差(有和没有泛型)显性、隐性、之差

2023-09-02 01:42:20 作者:风吃掉月亮

看到围棋四大行()方法如下:的

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?
}

请注意,通过第一呼叫生成的编译器的错误是: 的方法行动(T)的类型参数不能从使用推断。请尝试显式指定类型参数。的

Note that the compiler error generated by the first call is: The type arguments for method 'Action(T)' cannot be inferred from the usage. Try specifying the type arguments explicitly.

推荐答案

还有 MyAction的新动作(MyAction的)(当他们俩都有效),比前等将无法正常工作在C#1。这是一个隐式方法组转换。有很多次,这是不适用的,最显着的时候,编译器不能工作了,你想要什么样的委托,如:

There's no difference between MyAction and new Action(MyAction) (when they're both valid) other than the former won't work in C# 1. This is an implicit method group conversion. There are times that this isn't applicable, most notable when the compiler can't work out what kind of delegate you want, e.g.

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

本进场在你的问题,因为两者涉及的方法重载。这导致头痛,基本上

This comes into play in your question because both of the methods involved are overloaded. This leads to headaches, basically.

对于仿制药方 - 这是有趣的。法团并没有得到多少爱从C#3类型推断 - 我不知道这是否是要在C#4与否还有待提高。如果你调用一个泛型方法并指定类型参数,类型推断的作品相当不错 - 但是如果你尝试这样做反过来,失败:

As for the generics side - it's interesting. Method groups don't get much love from C# 3 type inference - I'm not sure whether that's going to be improved in C# 4 or not. If you call a generic method and specify the type argument, type inference works fairly well - but if you try to do it the other way round, it fails:

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));
    }
}

在C#3类型推断是非常复杂的,而且适用于大多数情况下(特别是它的伟大的LINQ),但未能在几人。在一个理想的世界里,它会变得容易理解的和的在未来的版本更强大......我们拭目以待!

Type inference in C# 3 is very complicated, and works well in most cases (in particular it's great for LINQ) but fails in a few others. In an ideal world, it would become easier to understand and more powerful in future versions... we'll see!