Delegates vs Interfaces in C#
Yes, delegates are in many ways like single-method interfaces. However:
- There is support built into the CLR for them
- There's support in the framework for them, including multi-cast abilities and asynchronous invocation
- There's additional C#/VB language support in the form of method group conversions, lambda expressions, anonymous methods
- They're mandated for events (i.e. events and delegates are a sort of matching pair)
- They mean you don't need to implement an interface in a separate class for each delegate instance you want to create.
The last point is the most important one - consider a LINQ expression of:
var query = collection.Where(x => x > 5)
.Select(x => x * x);
Now imagine if to express the logic of x > 5
and x * x
you had to write a separate class for each expression, and implement an interface: the amount of cruft vs useful code would be ridiculous. Now of course the language could have been designed to allow conversions from lambda expressions into interface implementations via separate classes, but then you'd still lose the benefit of being able to simply write a separate method and create a delegate with that as the target. You'd also still lose the multi-cast abilities.
As a similar thought exercsise, consider looping statements such as while
and for
. Do we really need them when we've got goto
? Nope. But life is much better with them. The same is true of delegates - and indeed properties, events, etc. They all make the development simpler.
The biggest practical difference is that you can provide different delegate instances for the same delegate from the same class, while you cannot do it with interfaces.
delegate void XYZ(int p);
interface IXyz {
void doit(int p);
}
class One {
// All four methods below can be used to implement the XYZ delegate
void XYZ1(int p) {...}
void XYZ2(int p) {...}
void XYZ3(int p) {...}
void XYZ4(int p) {...}
}
class Two : IXyz {
public void doit(int p) {
// Only this method could be used to call an implementation through an interface
}
}
From When to Use Delegates Instead of Interfaces (MSDN):
Both delegates and interfaces enable a class designer to separate type declarations and implementation. A given interface can be inherited and implemented by any class or struct. A delegate can be created for a method on any class, as long as the method fits the method signature for the delegate. An interface reference or a delegate can be used by an object that has no knowledge of the class that implements the interface or delegate method. Given these similarities, when should a class designer use a delegate and when should it use an interface?
Use a delegate in the following circumstances:
- An eventing design pattern is used.
- It is desirable to encapsulate a static method.
- The caller has no need to access other properties, methods, or interfaces on the object implementing the method.
- Easy composition is desired.
- A class may need more than one implementation of the method.
Use an interface in the following circumstances:
- There is a group of related methods that may be called.
- A class only needs one implementation of the method.
- The class using the interface will want to cast that interface to other interface or class types.
- The method being implemented is linked to the type or identity of the class: for example, comparison methods.
One good example of using a single-method interface instead of a delegate is
IComparable
or the generic version,IComparable
(Of T).IComparable
declares the CompareTo method, which returns an integer that specifies a less than, equal to, or greater than relationship between two objects of the same type.IComparable
can be used as the basis of a sort algorithm. Although using a delegate comparison method as the basis of a sort algorithm would be valid, it is not ideal. Because the ability to compare belongs to the class and the comparison algorithm does not change at run time, a single-method interface is ideal.
From Delegates Vs Interfaces in C#:
Delegates and Interfaces are two distinct concepts in C# but they share a commonality. Both delegates and interfaces only include the declaration. Implementation is done by a different programming object.