Thursday 23 February 2012

C# compiler bug - throw in single-line lambda

So I think I may have found a bug with the C# compiler. It's a pretty obscure case which I found when writing a unit test for an error handling module. It seems that the C# compiler won't allow single-line lambda functions to contain the throw keyword. Observe below:

static void Main(string[] args)
{
    ExecuteMethodAndHandleException(() => throw new Exception()); // compiler errors
}

static void ExecuteMethodAndHandleException(Action methodThatWillThrowAnException)
{
    try
    {
        methodThatWillThrowAnException();
    }
    catch (Exception ex)
    {
        // ...
    }
}

The above code generates 5 pre-compile errors, notably Invalid expression term 'throw', and ; expected. However the below works just fine:

ExecuteMethodAndHandleException(() => { throw new Exception(); });

It's a little more clumsy but it get's the job done, albeit with more noise than should be required.

So is this a bug? I did some digging and found nothing that indicated other people had found the issue. I did find something interesting on Stack Overflow regarding event wireups being prevented from expression tree lambdas. However in that case the compiler error is clear in its problem with the statement, CS0832: An expression tree may not contain an assignment operator. In my case the compiler errors differ slightly from pre-compilation errors, and the fact that a semicolon is expected before the closing method call parenthesis seems to indicate that the throw compiler semantics are expecting a semicolon irrespective of the context of throw.

Just for a laugh I tried the same thing in VB.NET and after getting to grips with the unfamiliar (but strangely sensible) syntax of their lambdas I found that the same compiler errors are NOT present in VB.NET (probably because they don't use semicolons, and don't allow multi-line lambdas). More indication this is a defect rather than intended behaviour.

Sub Main()
    ExecuteMethodAndHandleException(Sub() Throw New Exception())
End Sub

Sub ExecuteMethodAndHandleException(ByVal methodThatWillThrowAnException As Action)
    Try
        methodThatWillThrowAnException()
    Catch ex As Exception
        ' ...
    End Try
End Sub


EDIT: Submitted this bug report to Microsoft. We'll see what happens to it.

Sunday 12 February 2012

New design pattern? Single Responsibility Pattern

So I think I came up with a new design pattern. I can't be sure that I'm the first one to use it of course, but I couldn't find anything like it in my 2 or 3 minutes of hard searching, so I'm calling it the "Single Responsibility Pattern".

Ever since I read Clean Code by Robert C. Martin (thanks Xerxesb for the reading recommendation!), my entire attitude to code design and separation of concerns has changed. The Single Responsibility Principal has probably been the hardest thing to take on board and actually use, since for me the temptation is often too strong to resist to overload a class with several 'useful' features that really should be split off and abstracted away.

So the Single Responsibility Pattern has helped me out with this, and made code simpler at the same time.

Consider a class whose single responsibility is to load sales stats from a database or XML or some other source. Without turning this class into a 'manager' with many responsibilities, this is sortof what it starts looking like:


class SalesLoader
{
    SalesLoader()
    {
    }

    internal static void LoadSales()
    {
        new SalesLoader().LoadSalesInternal();
    }

    void LoadSalesInternal()
    {
        // strategy pattern comes in here
    }

    ...
}


By having a private constructor, and publishing only one static non-private method, this class becomes a single-responsibility utility class, that doesn't have to be instantiated needlessly every time it is called, cleaning up usage  code. We also don't have to worry about issues of memory leaks caused by Singletons persisting for the life of the program, plus I don't have to write static before every private implementation method, which is just a pain! By using the Strategy Pattern to control the actual implementation of LoadSalesInternal, we also don't have to worry about subclassing SalesLoader to provide new implementations of this functionality.