Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delegates (Lambda expressions) Vs Interfaces and abstract classes

I have been looking for a neat answer to this design question with no success. I could not find help neither in the ".NET Framework design guidelines" nor in the "C# programing guidelines". I basically have to expose a pattern as an API so the users can define and integrate their algorithms into my framework like this:

1)

// This what I provide
public abstract class AbstractDoSomething{
   public abstract SomeThing DoSomething();
}

Users need to implementing this abstract class, they have to implement the DoSomething method (that I can call from within my framework and use it)

2)

I found out that this can also acheived by using delegates:

public sealed class DoSomething{
   public String Id;
   Func<SomeThing> DoSomething;
}

In this case, a user can only use DoSomething class this way:

DoSomething do = new DoSomething()
{
  Id="ThisIsMyID",
  DoSomething = (() => new Something())
}

Question

Which of these two options is best for an easy, usable and most importantly understandable to expose as an API?

EDIT

In case of 1 : The registration is done this way (assuming MyDoSomething extends AbstractDoSomething:

MyFramework.AddDoSomething("DoSomethingIdentifier", new MyDoSomething());

In case of 2 : The registration is done like this:

MyFramework.AddDoSomething(new DoSomething());
like image 324
GETah Avatar asked Jun 11 '12 16:06

GETah


People also ask

What is the difference between lambda expression and delegate?

The difference really is that a lambda is a terse way to define a method inside of another expression, while a delegate is an actual object type.

Can we use lambda expression with abstract class?

Finally, an abstract class can't refer to a lambda expression, while the interface can have a single abstract method that can refer to a lambda expression.

In which of these situations are interfaces better than abstract classes?

In which of these situations are interfaces better than abstract classes? When you need to define an object type's characteristics, use an interface. When you need to define an object type's capabilities, use an abstract class.

Are lambdas delegates?

Again, lambdas are just delegates, which means that they can be used as an event handler without any problems, as the following code snippet illustrates.


2 Answers

Which of these two options is best for an easy, usable and most importantly understandable to expose as an API?

The first is more "traditional" in terms of OOP, and may be more understandable to many developers. It also can have advantages in terms of allowing the user to manage lifetimes of the objects (ie: you can let the class implement IDisposable and dispose of instances on shutdown, etc), as well as being easy to extend in future versions in a way that doesn't break backwards compatibility, since adding virtual members to the base class won't break the API. Finally, it can be simpler to use if you want to use something like MEF to compose this automatically, which can simplify/remove the process of "registration" from the user's standpoint (as they can just create the subclass, and drop it in a folder, and have it discovered/used automatically).

The second is a more functional approach, and is simpler in many ways. This allows the user to implement your API with far fewer changes to their existing code, as they just need to wrap the necessary calls in a lambda with closures instead of creating a new type.

That being said, if you're going to take the approach of using a delegate, I wouldn't even make the user create a class - just use a method like:

MyFramework.AddOperation("ThisIsMyID", () => DoFoo());

This makes it a little bit more clear, in my opinion, that you're adding an operation to the system directly. It also completely eliminates the need for another type in your public API (DoSomething), which again simplifies the API.

like image 154
Reed Copsey Avatar answered Oct 02 '22 11:10

Reed Copsey


I would go with the abstract class / interface if:

  • DoSomething is required
  • DoSomething will normally get really big (so DoSomething's implementation can be splited into several private / protected methods)

I would go with delegates if:

  • DoSomething can be treated as an event (OnDoingSomething)
  • DoSomething is optional (so you default it to a no-op delegate)
like image 37
Ortiga Avatar answered Oct 02 '22 10:10

Ortiga