In common with other big systems, thetrainline’s systems use a variety of technologies under the hood. Most of our code is written for the .NET framework, although there are bits of other technology stacks in there as well.
Recently, working with a project targeting version 3.5 of the .NET framework using Visual Studio, I came across a rather subtle gotcha.
Visual Studio 2010 was released in April 2010 and by default will target version 4 of the .NET framework. Version 4 of .NET came with, amongst other things, the following features.
- The Parallel extensions library.
- Dynamic dispatch.
- Named parameters.
- Optional parameters.
It was this last feature – optional parameters – that was the original source of this gotcha, leading to ‘error CS0241: Default parameter specifiers are not permitted’.
Suppose that you wanted to implement rational numbers in C#. So, I define the following class.
All well and good: I can now instantiate rational numbers and add them together, displaying the results as a nicely formatted string for all to see.
However, I now want to be able to initialize a rational number using a single numerator. In .NET 3.5, we can do this by introducing another constructor.
We can now initialize a rational with this constructor. In .NET 4, however, we can make use of optional parameters to get the same result; we can introduce a default value for the denominator in the original constructor, hence:
Targeting .NET 3.5
I now find out that this class needs to run under .NET 3.5 (because the target server has the NET 3.5 framework, but not version 4.0). Not to worry; we can change this using the Target Framework drop down in the properties window on our solution.
We change this to .NET Framework 3.5, and all again is well with the world.
Gotcha – ‘error CS0241: Default parameter specifiers are not permitted’
The problem arises when we now try to build this assembly with our automated, custom-built tools. These tools essentially use csc, the C sharp command line compiler. The program compiles fine from my computer:
Unfortunately, running this using the build tool gives me an error message when I try and deploy this on the server.
Rational.cs(10,56): error CS0241: Default parameter specifiers are not permitted
It actually gets worse: for the purposes of this blog post, I’ve built my program using an up-to-date version of csc for Visual Studio 2008: for servers that haven’t been updated with the latest compilers, the error you would receive is much more cryptic, pointing only to a syntax error.
Fix – Language Version C# 3.0
You may have figured out why this is happening: Visual Studio (and the 2010 version of csc) are clever enough to realize that the default parameter you’ve used is easy enough to translate into something that is easily understood by the CLR, and usefully ‘just does it’ for you. Older versions of csc, however, do not know about default parameters, and therefore throw a wobbly when you try and pass in a class that uses them.
This is because default parameters aren’t a new CLR feature in .NET 4.0, rather they are a piece of syntactic sugar introduced which does not require any change to the CLR to run. Visual Studio will nicely deal with these, as will its version of csc. To avoid this default behaviour of Visual Studio is a rather well-hidden secret: it is all there in an innocuous advanced settings button on the build properties page:
Choosing C# 3.0 from the ‘Language Version’ dropdown will make Visual Studio complain about all new C# .NET 4.0 language features, not just those that require new CLR features:
After doing this, Visual Studio now complains about your default parameter with a familiar squiggly red line. Again, all is well with the world: