bc-vnt Posted October 2, 2012 Report Posted October 2, 2012 Interfaces vs DelegatesBackgroundHaving different options can be great if one of the options is really more suited for a specific task, but having more options can also make decisions harder when different options have different advantages and disadvantages.I often need to stop and carefully think if an interface will or will not do a better job than a delegate and sometimes I even go back to my old code, that I initially implemented using delegates, to replace the delegates by interfaces. So, I decided it was time to write an article and show the advantages and disadvantages of both approaches.PerformanceI often see people asking if interfaces are faster than delegates or if delegates are faster than interfaces and then I see answers like: Interfaces are faster. Delegates are too damn slow; Delegates are faster because they are only a pointer to a method. Interfaces need to use a v-table to then find a delegate; They are equal, but delegates are easier to use.Well, those are not true. Maybe in .Net 1 delegates were really slower but, actually, the truth is: Delegates are faster... to execute. Interfaces are faster... to get.For example, in this code:Action action = SomeMethod;We are getting an Action (a type of delegate) to call SomeMethod. The problem is: delegates are reference types that contain both the instance and the pointer to a method. They are not a single pointer to a method and, by being reference types, they need to allocate memory. So, each time you transform a method to a delegate you are allocating a new object.If delegates were value-types that could be different, but they are not and we need to live with them this way.On the other hand, if we do this:IRunnable runnable = this;If the actual object implements IRunnable we simple get the same reference with a different cast. There is no allocation involved. So, when I saw a speed comparison like this:For Delegates:Stopwatch stopwatch = new Stopwatch();stopwatch.Start();for(int i=0; i<COUNT; i++){ Action action = SomeMethod; action();}stopwatch.Stop();Console.WriteLine(stopwatch.Elapsed);For Interfaces:Stopwatch stopwatch = new Stopwatch();stopwatch.Start();for(int i=0; i<COUNT; i++){ IRunnable runnable = this; runnable.Run();}stopwatch.Stop();Console.WriteLine(stopwatch.Elapsed); know that the interfaces are going to win. Not because they execute faster, but because at each iteraction a new Action delegate is allocated. But put the delegate getter and the interface getter outside of the loop and the delegate will be a little faster.When creating events, for example, we put the delegate only once on the event and then the event can be invoked thousands of times. That is, a single allocation is done.So, is there a winner?Well, for events (aside from the fact that the event keyword requires a delegate), delegates are really better.But before saying that delegates are better or faster, let's see different cases.Anonymous methodsIn my opinion anonymous methods are the worst use of delegates but, at the same time, are becoming the most common ones.When you do a call like this:for(int i=0; i<count; i++) MethodThatReceivesADelegate(() => SomeCall(i));The compiler is, in fact, creating an instance to hold the value of i. Then, it is creating another instance (the delegate) with a reference to that instance.If an interface was used instead, it will need to allocate a single object, which will implement the interface.Possible complainSomeone could complain that a single object is allocated to hold the value of i then, at each iteraction, the value inside that instance is changed. And it is even possible to argue that the compiler could optimize the delegate allocation, allocating it only once.Well, for the delegate allocation I don't know, but about a single instance to hold the i value that's true, and that's also a bug. If MethodThatReceivesADelegate is giving the delegate to another thread, such other thread may receive the wrong value of i. In .Net 4.5 such behavior was corrected. That is, at each iteraction a new object is created. This guarantees the good result if the delegate is given to another thread, but that also means that a new delegate instance should be allocated each time.If that MethodThatReceivesADelegate is going to use the delegate only once, using an interface would do a better job. Unfortunately, we don't have the option to implement anonymous interfaces.So, if it is for the convenience, the delegate will still be better. But if it is for performance, in this situation, an interface will be better because it will avoid one unnecessary allocation.In fact I created the IRunnable interface to force the users of my remoting framework to implement a new type instead of using anonymous delegates to solve the problem of the mutable i value used in fors (or any value used in foreachs, as both kinds of for share the same problem) but that also gave me a little performance benefit.Invoke and DynamicInvokeAt this moment we know that there are anonymous delegates but there are no anonymous interfaces and that for single use-cases interfaces will have a better performance than delegates because they will require a single object instead of two.This already makes me think if I should use a delegate or an interface when a method is going to receive a method to be executed but is going to execute it only once.But there are more situations we can use such objects that are also performance related.Do you ever need to call DynamicInvoke instead of the direct delegate invoke? Maybe because you don't know the delegate's parameter types at compile time?Well, having an interface you have the option to use a base interface to do the untyped call. I don't know why, but reflection invokes and delegates' DynamicInvokes are extremely slow, much slower than simple doing the casts, the array-length validation and putting a try/catch to generate the TargetInvocationException.So, if you have something like:public interface IDynamicInvokable{ object DynamicInvoke(params object[] parameters);}And then you create any of your delegate like interfaces as sub-interfaces of IDynamicInvokable, like this:public interface IAction<T>: IDynamicInvokable{ void Invoke(T parameter);}You will be giving your users the possibility to call your interface with the typed Invoke method or, if they don't know the exactly interface type at compile-time, they could use the more generic one, the IDynamicInvoke.Note: I hate the name generics. To me, the IDynamicInvokable is the most generic way to do the calls, and the IAction<T> is the typed interface. So, when I said generic I was refering the the the common and untyped way of doing the call, and not to generics, which are typed.So, if I am going to do thousands of calls to a delegate, but using DynamicInvoke instead of Invoke, an interface will do a better job.Again, I will question myself: Is the easy of use of anonymous delegates worth? Should I make it harder for the callers of my method only to have the best performance? Is this really going to impact the overall application performance?Different usesWe already have the Invoke and the DynamicInvoke. What about a TryInvoke?My last two articles talked about conversions and I will return to that kind of situation.If I use the Converter<TInput, TOutput> delegate, the conversion should work or should throw an exception. But exceptions are the wrong way to say that a conversion failed if the code is prepared to deal with invalid values.I considered creating another delegate (TryConverter) that, well, will return a boolean value to tell if the conversion worked and use an out parameter for the result.That will be great for the cases where we have an exception-free conversion, like int.TryParse, but if we don't have one (like when the conversion is done by a TypeConverter) we will need to catch the exception to return false.That's not a real problem. The problem is that I still want to give the version that generates exception. In such case, the exception will be caugh to return false, to then generate another exception. Terrible.But an interface solves such problem. With an interface we can have both methods, the Convert and the TryConvert.So, the Convert can use a conversion that throws an exception and the TryConvert can use a conversion that does not throws an exception.If there is only a conversion that throws a exception, then the TryConvert will be forced to catch the exception. If there is only a conversion that does not generates an exception and can fail, then the Convert will need to check for that and generate the exception, but we will avoid the case where an exception is caugh to return false to then generate another exception.In this case such versatility makes the interface the best solution, without a comparable delegate solution and surely giving better performance than a TryConvert only delegate.For those who read my other articles, you can expect an update of the Converters article to use the interface solution, which will support both Convert and TryConvert and the CastedGet will be eliminated as an untyped interface will do the job.ConclusionI still question myself if I should use an interface or a delegate for single-uses as delegates allow the use of anonymous delegates but, in general, I consider interfaces much more powerful and even better performing for the different situations. But let's finish by a small list of points:Delegates: Are reference-types, so they allocate an entire object only to reference a method; Are the fastest to call when you know all parameter types at compile-time; Allow the use of anonymous delegates which really simplify creating single-line or very small delegates; Can reference a private method without requiring to create a new type.Interfaces: Don't allocate new objects, so they are faster to get; Are faster for single-use cases, as only one object will be created instead of two; If well designed allow for generic (untyped) uses that are faster than DynamicInvoke of delegates; Allow different calling possibilities (like the Convert and TryConvert); Are a little slower to call with the rightly typed parameters; Don't have anonymous compile-time support; Require full types to be created even if a single method is needed.SampleThe sample application will only execute speed comparisons for the different situations.Initially all the tests were executing 100 million of iterations, but the DynamicInvoke was so slow that I decided to reduce the test to 10 millions of iterations.The output of this application on my work computer is:This application tests the speed of interfaces and delegates indifferent situations. Compile it in release and execute it outsideVisual Studio to get the right results.The following tests do 100 millions of iterations:Testing delegate speed, the wrong way: 00:00:01.6483403Testing interface speed, the wrong way: 00:00:00.5369746Testing delegate speed, the right way: 00:00:00.3757670Testing interface speed, the right way: 00:00:00.4831114Testing anonymous delegate speed: 00:00:01.7475340Testing an interface that does the same: 00:00:01.1950063The following tests do only 10 millions of iterations:Testing delegate's DynamicInvoke speed: 00:00:37.0368337Testing interface's DynamicInvoke speed: 00:00:00.3218726All the tests are finished. Press ENTER to exit.Download InterfacesVsDelegatesApp : InterfacesVsDelegatesApp.zip download - 2sharedhttp://www.codeproject.com/Articles/468967/Interfaces-vs-Delegates Quote