Introduction
I read Jason Roberts article on “Reducing code with target typed new expressions” the other day and it got me thinking. I’ve not looked at some of the new C#9 features as the code bases I work on regularly aren’t up to that level yet but I do like to investigate so this caught my eye. I’ve seen a few odd posts on Twitter about it on these small exposures to the functionality and the jury is currently out at the moment as to whether I like it or not.
Initial Thoughts
When I first saw it I thought it looked confusing and it made my spidey sense tingle. This has been the same for many of the new features brought to C# over the years. I especially remember when var
came to the language and I was very much against it. However as I’ve warmed to it I think it works well and I use it often. Due to this I am willing to give new language features a go, it doesn’t mean I have to always use them.
The target typed new expression I think has a time and a place. For me it is the opposite side of the spectrum from introducing var
.
As you’ll have seen throughout my blog posts over the years I am a strong believer of readable and maintainable code over “clever” code. If you, or another developer, in the future has to sit and look at code for a long time to work out what the “clever” syntax does is it worth it? This isn’t a blanket “let’s remove all clever code” however like everything “it depends” and there is a time and place for it.
Examples
Let’s talk through some basic examples to see when I can see it being useful and not.
List<string> original = new List<string>();
Let’s start with a simple generic list instantiation. This is the same as it’s been since generics were introduced in C# 2. This is still perfectly valid C# and although verbose it is clear what is trying to be achieved.
var list = new List<string>();
Then var
came along and made variable declaration/instantiation together less verbose. There are developers out there which don’t like this syntax. In this instance it is clear about what type the variable is however when you see the return value of a method assigned to a var
declared variable it might not be so obvious.
For me the target typed new has similar problems just on the other side of the equals sign.
List<string> list2 = new();
This is clear what is trying to be achieved although to be honest I think I prefer the var
version. As more code bases start to adopt the syntax maybe this opinion will change. Maybe it will come down to muscle memory as to which gets used. At the end of the day it compiles to the same and works the same so “shrug”.
The clarity starts to become a bit murkier when the type you are instantiating gets more complex.
public class MyOuter
{
public MyOuter(List<string> items) { }
}
Let’s take a simple POCO class which has a constructor which takes a List<string>
in it’s constructor.
MyOuter outer = new(new());
If we take a look at the usage of the constructor above you can see that this isn’t hugely clear what it is trying to achieve. You could argue that you don’t need to have the constructor details upfront initially but it still doesn’t quite look right to me and this isn’t a complicated constructor with dependencies which have complicated constructors! If you start chaining new(new(new(),new()))
etc. I can see it getting out of hand quite quickly!
Conclusion
As you can tell I’m not convinced by it at the moment. There is probably a Vanilla DI (dependency injection) movement somewhere which loves this syntax as all the items can be created in minimal space and fuss without the verbosity of fully qualified constructor usages and without the need of an IoC container. I could potentially see the usage in basic concepts but as complexity increased I currently think it would add confusion and not clarity. I’m yet to be convinced.
Let me know what you think on Twitter @WestDiscGolf. Am I missing something? Are you not convinced either? Let me know!