Jason Deacon Team : Web Development Tags : Technology Web Development Programming Rants

Upcoming C# 6.0 language features that I really don't like

Jason Deacon Team : Web Development Tags : Technology Web Development Programming Rants

Having used C# professionally for about 9 years now I have seen many iterations of the language, starting at the C# 1.1 days. I've seen it mature over the years to include some quite powerful features which make day to day tasks just that much easier, and that's a great thing.

But something happens when a product such as C# matures; with each version released the backlog of critical/important features diminishes and the product team starts to wonder "what can we add next time?".

Invariably this leads to less significant features being added over time and as we can see with the upcoming features in C# 6.0, features which start to not only be unhelpful, but actually hinder ongoing development. I'm going to briefly look at couple of them in this blog.

1. Primary Constructors

What happens now:

class Developer 
{
	private int _age;
	private int _concurrentprojects;
	
	public Developer(int age, int concurrentProjects) {
		_age = age;
		_concurentProjects = concurrentProjects;
	}
}

What you will be able to do in C# 6.0

class Developer(int age, int concurrentProjects) 
{
	private int _age = age;
	private int _concurrentprojects = concurrentProjects;
}

Why is this not-so-good?

First of all this is just syntactic sugar being interpreted by the compiler. The resulting IL is actually exactly the same between the two examples except what we have done is increased the cognitive load of developers who have to maintain this class later on, and for what? 20 seconds of typing saved? It could get worse though simply by adding another constructor to the class..

class Developer(int age, int concurrentProjects) 
{
	private int _age = age;
	private int _concurrentprojects = concurrentProjects;
	private bool _hasCats;
	
	public Developer(int age, int concurrentProjects, bool hasCats) : this(age,concurrentProjects) {
		_hasCats = hasCats;
	}
}

As you can see we now have a 'traditional' constructor which feeds the 'primary constructor', so two constructors which are implemented in two different ways. This is not a recipe for easy maintenance.

Furthermore, what happens when we actually want to add some validation or method call to our primary constructor (set aside your 'best-practice' arguments of even doing those things in constructors for now)? We have to create a traditional constructor and refactor the primary constructor away, thus losing the benefits of using it in the first place.

One thing I'm not sure about however is how scoping works with regards to the variables in the primary constructor and variables declared in that class' methods, which could lead to further confusion, especially for maintainers. I just don't really see a point.

Also, it feels like javascript. Disclaimer: I don't like javascript.

2. Primary constructors can be used to intialise auto properties

Same as the above example, except we can write:

class Developer(int age) 
{
	public int Age {get;set;} = age;
}

as well as..

class Developer(int age) 
{
	public int Age {get;} = age;
}

The second example here is something which, in my opinion, actually offers some tangible benefits simply because you don't have to specify a private setter on that property, however the benefit is negligible while the time taken to understand what is happening is not.

3. Declare static classes in a using statement for method shortcuts

What happens now:

using System;

class Developer 
{
	public PrintHowManyCats(int cats)
	{
		Console.WriteLine("Developer has {0} cats", cats);
	}
}

What you will be able to do in C# 6.0

using System.Console;

class Developer 
{
	public PrintHowManyCats(int cats)
	{
		WriteLine("Developer has {0} cats", cats);
	}
}

At first this example confused me when I saw it because you have never been able to use 'using' for actual classes that you weren't aliasing (eg "using SuperAwesomeConsoleAlias = System.Console" is currently valid but typically frowned upon). But once I realised what it was doing, I frowned, a lot. This will confuse programmers that work on real code in the real world and the results won't be pretty.

While I'm a strong advocate of "less code is better code", the immediate implication of this feature means that programmers may well misinterpret the source of a method and, for example, assume things are being handled by a "WriteLine" method in the Developer class rather than by a static class included through using. I'm sure there will be appropriate scoping warnings in Visual Studio to indicate that there is a potential scoping conflict but I don't know if that will be enough to have developers not chasing their tails in some circumstances.

Conclusion

These are just a couple of the features that I think will end up being more harmful than helpful and hopefully I've explained my reasoning on why I think that.

Time will tell though, as I was initially very opposed to var in C# but I've come around on it's usefulness.