A silly C# trick from the trenches

UPDATE: as Joe rightly points out in the comments (thanks Joe) when you try to pass a Func<T,V> to a method expecting Action<T> using lambda syntax it doesn't fail. Somehow the compiler must realize there is no match for Func<T,V> and look for a match for with Action<T> as a parameter. I don't know how I missed this. I suppose this just means that the s => {Func(s);;} syntax is even less useful than I had originally thought, you need a competing overload that does accept Func<T,V> which would take precedence... don't think that is very likely. So now it is a super silly trick. Sorry for the confusion everyone.

I’ve been playing around with a Fluent API for something.

Most of you will know that fluent API generally allow you to chain method calls together, so rather than writing this:

var pconfig = tconfig.ForProperty(t => t.Firstname);
pconfig.MaxLength(100);
pconfig.Nullable();

With a fluent style API you might do this instead:

tconfig.ForProperty(t => t.Firstname).MaxLength(100).Nullable();

All you need to make this the work is have MaxLength(..) and Nullable() return this.

So far so good.

But then I noticed something interesting.

I found that I occasionally need to be able to call these fluent methods in situations where I could care less about the return value. I.e. I have no intention of chaining another call.

Usually this sort of thing is benign.

If you don’t want to use the return from a method, well... don’t.

Things get a little more interesting inside a lambda though.

Let me explain how.

Imagine you have a method like the one below,

public Configuration<T> Configure<T>(
T t, Action<string> callback
);

Notice that one of the parameters is an Action<string> i.e. a method that takes one string parameter and returns void.

Now imagine you have a function like this:

public MyClass DoSomething(string value){
// Doesn’t really matter what this does with the
   // value so long as it returns non void.
return this;
}

That does what we really want to do in the callback AND additionally returns something.

Well as you might have guessed the ‘AND additionally’ can cause problems when writing lamdbas, because this:

var x = Configure(entity, (s) => DoSomething(s));

… won’t compile, the Lambda has the wrong type.

Hmm…

The solution is remarkably simple, make a multi-line lambda:

var x = Configure(entity, (s) => {DoSomething(s);;});

As you can see the second line does nothing.

Except, and here's the silly trick, changing the type of the lambda so it returns void… as required.

Next time you see ;; don’t assume it is a typo ;)