On February 5, 2004 Eric Gunnerson, Program Manager on the Visual C#, published an article on msdn where he explores the performance aspects of various methods of calling code dynamically.
Because the method called does a trivial amount of work, it will accentuate the differences that you see between different methods. The more work the method does, the less difference there will be between the different methods of calling, and therefore big differences here may be inconsequential in actual code.
Figure 1 is a pretty picture of the results for Visual Studio 7.1, when calling a method 100,000 times:
Figure 1. Screenshot of results
It isn't surprising that the direct call is the fastest. The call that is being made can be easily put inline by the JIT, which means that there is no call overhead. Interfaces suffer compared to direct calls because they can't be put inline (and this is true of virtual calls as well). Delegates are a bit slower than interfaces.
InvokeMember() is very slow, with interface calls being some 200 times faster than InvokeMember() calls. InvokeMember() does a tremendous amount of work to make sure it is called safely and that it is calling the right method, and this shows. Similarly for the custom delegate case, calling DynamicInvoke() does a lot of work to make sure the call is okay.
The CustomClass version works okay, but it suffers from a lot of overhead in creating the custom class in the first place, which means it's only about 5 percent as fast as a direct call for 100,000 calls. As the number of calls goes up, the overhead will matter less, and it will be roughly the speed of the interface call.
What About Whidbey ?
In Whidbey, the results are much the same, with the exception of the delegate case, which has been optimized, and now provides similar performance to interfaces. So, if you were unhappy with the performance of delegates, you should be happier with what you get in Whidbey.