Wednesday, December 22, 2010

C# Closure Constructors

I’ve been doing quite a lot of Javascript recently, one of the Javascript patterns I’ve been using extensively is Douglas Crockford’s closure based class construction. It just struck me today that you could do something similar in C#.

Here’s a cool cat:

public class Cat
{
protected Cat(){}

public static Cat New(string name)
{
return New(name, null);
}

public static Cat New(string name, Cat parent)
{
var self = new Cat();

self.GetParent = () => parent;
self.SayHello = () => "Hello, my name is " + name;
self.MakeKitten = kittenName => New(kittenName, self);

return self;
}

public Func<string> SayHello { get; protected set; }
public Func<Cat> GetParent { get; protected set; }
public Func<string, Cat> MakeKitten { get; protected set; }
}

Which you can use like this:
 
var cat = Cat.New("Timmy");
var kitten = cat.MakeKitten("Jenny");

Console.WriteLine(kitten.SayHello());
Console.WriteLine(kitten.GetParent().SayHello());

Which outputs:

Hello, my name is Jenny
Hello, my name is Timmy

The interesting thing is that you don’t have to declare any private class fields, all the state is encapsulated by the closures created in the constructor. It would be easy to define different Cat behaviours just by providing different implementations of SayHello, GetParent and MakeKitten at runtime.

What do you think? Could there be any benefits to creating classes like this? Obvious drawbacks?

Don’t take this too seriously, I’m not for a moment suggesting that you refactor your code.. just playing :)

6 comments:

Michael Foord said...

It has all the same problems with testability that Javascript closures have. But then you already have that with private members in C# *anyway*.

Jim Bolla said...

I use a similar pattern from time to time. Usually when it's simpler/terser to define a class with Func<> and Action<> properties that can be set to one line lamdas during construction instead of creating an interface with several implementers with a bunch of one liner method implementations.

Peter said...

I like it! But I don't see any immediate benefits. But that doesn't make it any less cool.

Alan Huffman said...

That's interesting. The only benefit to something like that would be changing behavior on the fly or swapping out behavior.

Damian Powell said...

Very cool. If the setters were public, then it strikes me that this could be a useful pattern for implementing AOP without needing to use interfaces implemented as decorators.

Stephane said...

got there through a more recent post about closure.
I use exactly this to simplify datetime mocking:

public static class SystemTime{
Now = ()=>DateTime.Now;
}

This lets you get datetime now in your code with and override it very easily in your tests by redefining it.
It was a trick from ayende I believe.