Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
610 views
in Technique[技术] by (71.8m points)

c# - The difference between implicit and explicit delegate creation (with and without generics)

See the four lines in the Go() method below:

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

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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.

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

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!


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...