# Thursday, May 28, 2009

This is really nothing new, but I don't think I've explicitly stated this before: It makes a lot of sense to view delegates as anonymous one-method interfaces.

Many people liken delegates to function pointers. While that's probably correct (I wouldn't really know), it's not a very object-oriented view to take – at least not when we are dealing with managed code. To me, it makes more sense to view delegates as anonymous one-method interfaces.

Lets consider a simple example. As always, we have the ubiquitous MyClass with its DoStuff method. In this example, DoStuff takes as input an abstraction that takes a string as input and returns an integer – let's imagine that this is some kind of Strategy (notice the capital S – I'm talking about the design pattern, here).

In traditional object-oriented design, we could solve this by introducing the IMyInterface type:

public interface IMyInterface
{
    int DoIt(string message);
}

The implementation of DoStuff is simply:

public string DoStuff(IMyInterface strategy)
{
    return strategy.DoIt("Ploeh").ToString();
}

Hardly rocket science…

However, defining a completely new interface just to do this is not really necessary, since we could just as well have implemented DoStuff with a Func<string, int>:

public string DoStuff(Func<string, int> strategy)
{
    return strategy("Ploeh").ToString();
}

This not only frees us from defining a new interface, but also from implementing that interface to use the DoStuff method. Instead, we can simply pass a lambda expression:

string result = sut.DoStuff(s => s.Count());

What's most amazing is that RhinoMocks understands and treats delegates just like other abstract types, so that we can write the following to treat it as a mock:

// Fixture setup
Func<string, int> mock =
    MockRepository.GenerateMock<Func<string, int>>();
mock.Expect(f => f("Ploeh")).Return(42);
var sut = new MyClass();
// Exercise system
string result = sut.DoStuff(mock);
// Verify outcome
mock.VerifyAllExpectations();
// Teardown

Whenever possible, I prefer to model my APIs with delegates instead of one-method interfaces, since it gives me greater flexibility and less infrastructure code.

Obviously, this technique only works as long as you only need to abstract a single method. As soon as your abstraction needs a second method, you will need to introduce a proper interface or, preferably, an abstract base class.

Wednesday, April 07, 2010 9:47:43 AM (Romance Daylight Time, UTC+02:00)
"While that's probably correct (I wouldn't really know), it's not a very object-oriented view to take."

We shouldn't believe that delegates are unlike a function pointer just because the latter is not object-oriented. The shoe ... fits. Furthermore, I would argue that an anonymous one-method interfaces is not a first-class object-oriented concept; we can describe it with words, but I doubt that you will find any of the non-.NET literature talking about such a thing. Well ... I will grant that mention might be made under a description of the command pattern.

"Obviously, this technique only works as long as you only need to abstract a single method."

Yes. Then we are in trouble and we didn't even swim that far from shore.

What was the problem? We focussed too much on a method and we ignored the interface. An interface defines the contract of which the method is only a part. The contract is identified by the name of the interface. There is no contract defined by method signatures. "Takes an int and a double and returns a string" doesn't mean anything.

In summary, focussing on the method is every bit as dirty as ... function pointers.

Sincerely,
jonnie savell
jonnie savell
All comments require the approval of the site owner before being displayed.
Name
E-mail
(will show your gravatar icon)
Home page

Comment (Some html is allowed: a@href@title, b, em, i, strike, strong) where the @ means "attribute." For example, you can use <a href="" title=""> or <blockquote cite="Scott">.  

Enter the code shown (prevents robots):

Live Comment Preview