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);

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.


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 😉

Comments (7)

  1. DarthObiwan says:

    I had just noticed the same thing the other day while I was implementing a generic calendar control that took in a selector function. I had accidentally typed two semi-colons and got a compiler error, I noticed it was a type mismatch and not just a syntax error.

    This is definitely one of those little tricks that are good to know and watch out for. I had always found it odd that C# allowed ; to show up on its own.. you can have 20 lines of ; without a problem. Now it actually has a use.

  2. Interesting, I’ve never thought that was possible but it sure is  a neat way of doing any type of configuration!

  3. jtenos says:

    Nice trick – I’ve done this the long way, but never seen it written like this.  I’d be a little concerned that it’s not really easy to read, but it might just have a place.

  4. Alex D James says:

    @DarthObiwan (nice mix of names by the way… I didn’t know Obiwan was a Sith spy!). Good sleuthing.

    @Jtenos, I agree about it being a little hard to read, grok, explain etc. If you use it in your code just put a hyperlink to this post 😉

    @Mikael its nice to hear that you think it is useful. Sometimes I see myself writing this kind of stuff and I really wonder…

  5. Joe Enos says:

    Just copied some of your code to try for myself, and found that it actually does work for me without the special syntax:

    public Configuration Configure(Action<string> callback) { return null; }

    public MyClass DoSomething(string value) { return this; }

    // No compiler problems

    var y = Configure(s => DoSomething(s));

    // Compiler error

    var z = Configure(DoSomething);

    // Compiler error

    var k = Configure(delegate(string s) { return DoSomething(s); });

    // No compiler error

    var j = Configure(delegate(string s) { DoSomething(s); });

    No compiler errors or warnings on the full lambda.  No compiler error on the old-style anonymous method either, but I wouldn’t expect one there.

    I’m on .NET 3.5 SP1 using VS2008.

  6. Alex D James says:


    Well don’t I feel like an idiot!

    Thanks for point out the error of my ways.

    I thought I had checked this out, but obviously not, I made a stupid assumption.

    looks like I have to eat some humble pie.


  7. Joe Enos says:

    No problemo…Definitely a good discussion point.  It was kind of weird that a simple lambda works when passing in just the name of the method doesn’t work.  I wonder if that kind of thing will be dealt with in the 4.0 compiler, since they’re doing a lot of covariance stuff, and that’s kind of a similar concept.

Skip to main content