2

Possible Duplicate:
Why must a lambda expression be cast when supplied as a plain Delegate parameter

Control.Invoke accepts a Delegate parameter type. I cannot pass a lamba expression as a Delegate without telling the compiler which type of delegate I'm passing.

textBox1.Invoke(() => { MessageBox.Show("Hello World"); }); //illegal

In this case, I can cast to Action

textBox1.Invoke((Action)(() => { MessageBox.Show("Hello World"); })); //legal

However, I can create a shorthand method via an extension method (I've seen Marc Gravell do this):

public static void Invoke(this Control control, Action action)
{
    control.Invoke((Delegate)action);
}

Now my shorthand works...

textBox1.Invoke(() => { MessageBox.Show("Hello World"); }); //legal

How is it that the compiler can determine that an anonymous method is an Action in the extension method, but the compiler cannot determine a lamba is an Action and therefore a legal Delegate in the case of Control.Invoke?

Community
  • 1
  • 1
P.Brian.Mackey
  • 43,228
  • 68
  • 238
  • 348
  • @DanielBruckner - That question is similar, but it does not address my question. I am looking into two distinct, similar scenerios. I want to understand why one case is implicit and the other case requires explicit. I am asking about this specific incongruity, not the workaround...which I've already defined in the OP. I suspect the answer has to do with Method Invocation. – P.Brian.Mackey Jan 23 '13 at 19:06
  • I think Jon Skeet states it quite clearly - the compiler does not know the type of delegate to create because there can be several delegates with the same signature. For example `System.Predicate` and `System.Func` have the same signature taking something of type `T` and returning `Boolean`. Now the compiler is just unable to figure out if `x => x == "something"` should become an instance of `Predicate` or of `Func`. – Daniel Brückner Jan 23 '13 at 19:09
  • @DanielBruckner - Ok...look at it this way. What if I add more Extension Methods? Some with Expression tree overloads to create a clear ambiguity? – P.Brian.Mackey Jan 23 '13 at 19:10
  • 1
    @P.Brian.Mackey: Try it and you'll get your answer. – Allon Guralnek Jan 23 '13 at 19:14
  • You have to remember that `control.Invoke(() => DoSomething());` is syntactic sugar for `control.Invoke(new Action(CompilerGeneratedFunction));`. How can the compiler possibly come up with the class `Action` if the signature of `Control.Invoke` only states that the parameter is of type `Delegate`? – Daniel Brückner Jan 23 '13 at 19:19

1 Answers1

0

First, the compiler is smart enough to determine that the parameter is of type Action (as opposed to say Action<T>). More importantly, the compiler can assume I mean an Action as opposed to an Expression because the ambiguity is removed. If I do something silly to recreate ambiguity...say create an overload via a new extension method:

    public static void Invoke(this Control control, Expression<Action> action)
    {
        Console.WriteLine("hi");
        //control.Invoke((Delegate)action);
    }

The compiler will catch that as well:

The call is ambiguous between the following methods or properties:

The comments made walked me to the answer I'm looking for.

P.Brian.Mackey
  • 43,228
  • 68
  • 238
  • 348