C#: Object Initializer and The Horse Shoe
The object initializer syntax introduced in C# 3.0 makes it easier for us to initialise our objects in one statement but I think we need to remember that they are not named parameters and that there is still a place (a very good one actually) for creating objects from constructors or factory methods.
Unfortunately what I think the cleaner syntax does is encourage us to create objects with half the fields populated and half of them null by default.
When we didn't have the object initializer syntax we would have to set properties on objects like so:
var foo = new Foo(); var bar = new Bar(); bar.Baz = new Baz(); foo.Bar = bar;
It takes a lot of extra boiler plate code to achieve this and it looks terrible, hopefully driving us towards using the constructor to initialise our objects.
Object initializers makes it much easier to achieve the same thing but at its worst we end up with code similar to the following which to me looks a bit like a horse shoe, an anti pattern in my opinion.
new Foo { Bar = new Bar { Baz = new Baz { Other = new Other { Value = "value", OtherValue = "otherValue" } } } }
I don't think we should write code like this – to me it's not expressive and it's difficult to understand why certain fields are set or not set. You end up having to think how this code fits into the bigger picture in order to understand it – extra context which shouldn't be necessary.
From experience we also end up in the debugger much more frequently than should be the case, trying to work out why certain fields are set. I feel this leads to very implicit code where you have to work out what is going on/where you are in the work flow by checking the state of our objects.
Of course the problem here is the reliance on properties (i.e. getters/setters) to instantiate our objects rather than object initializer in itself but the new syntax has made it much easier for us to do it.
Certainly there are some times when it's quite nice to have the object initializer syntax but as with most things we need to be careful not to overdo it.
I think this, as with so many things in software development, isn't an either/or question, it's a when.
C# gives us the tools, but it's up to us to use them wisely and appropriately.
If a given property should always have a value, then the design of the class and its constructor(s) should be such that this is guaranteed — null values shouldn't even be a possibility.
If a developer is coding and winds up with the horseshoe code above, then its time for him to work on his coding style — but I'd have the same issue with something like this:
new Foo(new Bar( new Baz(new Other("value","otherValue")));
In my opinion, this is no more readable than the other example, so it's not necessarily the tool, but the person using it that's the problem.
For me, the right use of this tool is in combination with constructors, not in place of. The constructor is for required fields at a minimum and initialization is for those that aren't available in the constructor.
Paul
16 Feb 09 at 11:20 pm
[...] C#: Object Initializer and The Horse Shoe – Mark Needham [...]
Arjan`s World » LINKBLOG for Feburary 16, 2009
17 Feb 09 at 7:10 am
[...] C#: Object Initializer and The Horse Shoe – Mark Needham looks at object initialisers and how they can lead to messy 'horse shoe' like code [...]
Reflective Perspective - Chris Alcock » The Morning Brew #288
17 Feb 09 at 6:39 pm
[...] is the main reason I find the C# object initializer syntax such a nightmare – it gets blatantly abused and you end up with half constructed objects all around [...]
Coding: Good Citizens at Mark Needham
5 Mar 09 at 12:00 am
[...] written previously about my dislike of the way the object initialiser is misused in C# 3.0 and although I've also written about my preference for explicit modeling and the need for objects [...]
Coding: Setters reduce trust at Mark Needham
23 May 09 at 4:37 pm
[...] C# we would typically make use of the object initializer syntax to do this, but in F# I've been writing code like this to do the same thing: type [...]
F#: Setting properties like named parameters at Mark Needham
29 Jun 09 at 12:30 am
[...] benefit of this approach is that it means we can make use of the object initializer to setup test data – perhaps one of the few occasions when it seems to be reasonably [...]
Builders hanging off class vs Builders in same namespace at Mark Needham
15 Aug 09 at 10:56 am