While catching up with a friend for (a very geeky) lunch the other day, a few ideas crystalised into another idea for the next version of C#.

The lambda expression syntax introduced in C# 3.0 is a brilliant step forward from the anonymous delegates of C# 2.0, but one thing has always irked me - that a lambda expression with no parameters needs to be written this way:

() => expression

Clearly, you need specific syntax to identify a lambda expression, but is this really the best they could do?

I have a suggestion to make: For a parameterless lambda expression, why can’t we just write a block, surrounded by braces. So, instead of these:

Action a = () => { MyVoidMethod(); };
Func<bool> b = () => { return MyBoolFunction(); }

We should be able to write

Action a = { MyVoidMethod(); };
Func<bool> b = { return MyBoolFunction(); }

(And, yes, I’m aware that there are simpler ways to write those first examples, ways that are still valid C#. Bear with me, there is a point to my rambling.)

Now, let’s throw a new piece of parameter syntax sugar into the mix. Hopefully you’ll be aware of the params keyword that allows you to write methods that take a variable number of parameters:

void Promote(params Person[] peopleToPromote) {  }

void Demo()
{
    Promote( fred, wilma, barney, betty);
}

You can only use the params keyword for the last parameter - the compiler will throw an error if you put it somewhere else, or if the type given is not an array.

Let’s introduce a new keyword, block that can only be used for the last parameters of the method, and only if those parameter types are delegates with no parameters. The purpose of this parameter is to allow callers to put the implementation of the block following the apparent method call, instead of within it.

If we take both of these ideas, we can change the code we write from this:

void Context(string label, Action action) {  }
void Demo()
{
    Context("Doing a Demo", () => { PerformDemo(); });
}

Into this

void Context(string label, block Action action) {  }
void Demo()
{
    Context("Doing a Demo")
    { 
        PerformDemo(); 
    };
}

A little bit of syntactic sugar has given us a nice way to craft apparent C# extensions, that work along the lines of the existing using statement.

But, wait, you say - when you described the block keyword, you used the word parameters - what happens when you have multiple block parameters in your method signature?

I’m glad you asked. ;-) In line with the way that named parameters work in C# 4.0, I suggest each block should be prefixed by the name of the parameter being supplied. How would this look?

First, we declare the method itself - perhaps one to support writing transactional programs:

void Transaction(string label, block Action action, block Action commit) {  }

void Demo()
{
    Transaction("A demo transaction")
    action
    {
        
    }
    commit
    {
        
    };
}

Or perhaps, one that that forms part of a “design by contract” API:

void Contract(string context, block Action requires, 
              block Action execute, block Action ensures) {  }

void Demo()
{
    Transaction("A demo transaction")
    requires
    {
        
    }
    execute
    {
        
    }
    ensures
    {
        
    };
}

So, what does this bit of syntactic sugar give us? Roll your own language extensions.

There are a few obvious ways to enhance this - such as allowing blocks to break out delegates that take parameters, but I’ll leave those as an exercise for the reader.

Comments

blog comments powered by Disqus
Next Post
Sharpening the Saw  18 Apr 2011
Prior Post
On Comments and Spam  01 Apr 2011
Related Posts
Browsers and WSL  31 Mar 2024
Factory methods and functions  05 Mar 2023
Using Constructors  27 Feb 2023
An Inconvenient API  18 Feb 2023
Method Archetypes  11 Sep 2022
A bash puzzle, solved  02 Jul 2022
A bash puzzle  25 Jun 2022
Improve your troubleshooting by aggregating errors  11 Jun 2022
Improve your troubleshooting by wrapping errors  28 May 2022
Keep your promises  14 May 2022
Archives
April 2011
2011