System.Delegate is not a delegate type…
I think anonymous methods are a great feature, and I use them where I can to improve code readability. I thought they would be especially useful in Windows Forms controls, if you want to execute a small piece of code on the UI thread using the Control.Invoke method.
The Control.Invoke method takes a Delegate parameter, so I figured I could just do something like:
this.Invoke( delegate { this.Text = "x"; } );
Well, I was wrong, it seems that a conversion from an anonymous method (a delegate) to a Delegate is not something trivial and I got this compiler error:
Argument '1': cannot convert from 'anonymous method' to 'System.Delegate'
So, I tried to help a bit by explicitly casting the thing…
this.Invoke( (Delegate) delegate { this.Text = "x"; } );
Which lead to this nice compiler error:
Cannot convert anonymous method block to type 'System.Delegate' because it is not a delegate type
So now it’s telling me System.Delegate is not a delegate type… To the msdn library! Aha, just like the compiler said:
The Delegate class is not considered a delegate type; it is a class used to derive delegate types.
MethodInvoker is a delegate type however; and one I used to use a lot, so let’s cast the anonymous method block to that one…
this.Invoke( (MethodInvoker) delegate { this.Text = "x"; } );
Bingo, it worked!
I find this kinda confusing - I’d suspect that the compiler could see anonymous methods as delegate types without the need to cast them - not to mention that it looks ugly, and I wanted my code to be more readable.
Oh well, this’ll work too I guess :/
Wednesday 15 Nov 2006 | Guy Mahieu | .net(t) , c#(t)
Just what I needed to cement my understanding. Thanks.
I just ran into the same problem, and found your blog looking for answer. I think they should fix this in a future version. In the meantime, if you do alot of this you can define another Invoke method that takes a MethodInvoker. Apparently the compiler can convert from anoymous method or lambda to a MethodInvoker without a cast.
// on the Form class
void FormThreadInvoke(MethodInvoker del)
{
Invoke(del);
}
…
FormThreadInvoke(
delegate() { this.Text = “x”; }
);
// or in 3.0…
FormThreadInvoke( () => this.Text = “x” );
Ah, great! That is EXACTLY what I needed! Thanks SO much!
This makes the Control.Invoke code so much better.
Thanks again
Thank YOU!
Great decision of the problem!
Thanks yet again :)
Thank you VERY much !
Nice post, helped me wrap my head (again) around anonymous method casting.
“Well, I was wrong, it seems that a conversion from an anonymous method (a delegate) to a Delegate is not something trivial and I got this compiler error”
If it wasn’t trivial we couldn’t do this:
(MethodInvoker) delegate { this.Text = “x”; }
Because that is doing exactly that (conversion from an anonymous method (a delegate) to a Delegate) - it’s like the guys on the CLR did all this work for the anonymous method sugar but then kinda stopped halfway on certain parts. Unless I’m overlooking something completely (which is more than likely).
This is helpful if you have System.Windows.Forms.dll referenced; however, if you are getting this error and aren’t doing GUI programming, use an Action object. Specifically, try something like this:
Action d = delegate()
{
var ct = Thread.CurrentThread;
Trace.TraceInformation(”TID {0}: State: {1}”, ct.ManagedThreadId, ct.ThreadState);
};
var ar = d.BeginInvoke(callback, null);
[...] be necessary to make this work. That’s pretty nice! (A similar approach is taken here.) But it’s still not quite as slick and intuitive as I’d like. By creating [...]
Just wanted to say your post helped me a lot…
thanks buddy,
-Vahe
Werd. Just what I needed.
Thanks. This was just beginning to drive me nuts…
Fantastic! Your steps were very clear. I’m so glad you outlined your attempts at the obvious solution, including the error messages you got along the way. I tried those exact same steps, just was missing the “MethodInvoker” piece of the puzzle.
You’ve made the world a better place. Thanks so much for this info.
- wyck