If you disassemble this version and have a look at the IL you’ll see the MethodInvoker is newobj‘d every pass through the loop. Curious… can’t C# just unroll this version? If not, why not? So while the short hand, inline looks great and probably the nicest to maintain, beware the potential performance costs (unecessary allocations of the delegate) as opposed to this far less elegant, yet more efficient approach:

I guess my next question is for all the real hardcore folks out there that like to get into the JIT’d machine code: Is it unrolled by the JIT? I guess I could just attach the profiler and see how man MethodInvoker’s are actually instantiated at runtime, but I’m only running C# Express on this box so I don’t have it and AFAIK there’s no “official” CLR Profiler for .NET 2.0 yet.

On a related note, I find it really annoying that I have to do new MethodInvoker at all. Why can’t I just do:

this.Invoke(delegate()
{
this.label1.Text = work.ToString();
});

I guess in the particular case of Control::Invoke I can understand the need to know exactly what kind of delegate instance to construct because it takes Delegate which is an abstract class. However, even when the type of delegate could be inferred from the method signature it is not. :

Share this:

Leave a comment

I’m at home and don’t have a .NET 2 install available, but in general, you cannot infer delegate type based on the argument list at the caller’s site. Two delegate types with identical signature are still different.

I just tried this and it doesn’t compile; delegate types *really* have a strong identity and the compiler won’t let you play loose with them (typecasting fails as well).

Hey, thanks for the feedback. What you say about the delegates being strongly typed is certainly true. It’s been this way since day one as you mention. What I’m saying though is that when I specifically declare an anonymous method in the place where a delegate should be passed, if the signature of the method is statically distinguishable as a certain delegate type the compiler still forces me to do the new FooDelegate(…). This seems to go against the compiler’s ability to determine the right delegate for event handlers in C# where you never need to do the new FooHandler(…).

Like I said, I can understand the need to be explicit if I am calling a method with a signature where it is unclear as what delegate type should be inferred just based on signature (i.e. the Control::Invoke).

Ah – getcha. You are correct that the compiler could go looking for delegate types that match the signature. The cases where the compiler does get it right is when the delegate type is specified in the callee’s site, such as

private void CallMe(StringCallback callback) { }

Which you can invoke with CallMe(delegate(string argument) { /*code*/ });

You can still confuse the compiler (or rather, cause it to fail with an ‘ambiguous call’ error), by introducing an overload that takes a delegate of a type with compatible signature (say, an overload of CallMe with OtherStringCallback). In this case, you can always specify the delegate type directly like you do in your Invoke example, and it should work.

Fun stuff for a Wednesday morning, which had me firing up VS to double-check what I’m saying. 🙂