c# constructors vs auto-properties and object initializers
Asked Answered
T

3

8

I have used auto properties a lot but I have gone more and more away from that setting up classes with readonly backing fields initialized in the constructor. I remove all setters and only add the back if the property clearly need a setter.

I find this makes my classes more robust and elegant OO wise and I am kicking myself for not doing this earlier.

I find constructors are very underused generally in c# code examples and I think auto-properties and object initializer are a big part of this, so my question is why does the c# team push features like this and not is focusing more on deliver features pushing best practices more. Generally I think its too easy writing bad code and believe more could be done helping coders write good code

Trichinize answered 3/9, 2010 at 23:2 Comment(1)
Not all types must be immutable. It is perfectly common (and wholesome) to take a mutable type in a constructor, then copy it to a private member. Then it is shielded from changes via outside code (assuming it does the same thing for any mutable dependencies). This is especially true for plain-old-data objects.Salem
O
13

From conversations, I believe the C# team understands that they've made it easier to write mutable types while not providing similar benefit for immutable types. It's not that they've made immutability any harder over time - they just haven't made it any easier... except for anonymous types, which are immutable, but have various other drawbacks. I certainly wouldn't wish automatic properties to be taken away - where they're appropriate, they're really useful. I'd just love to have the equivalent for readonly properties (allowing them to be set just in the constructor).

I've found that C# 4's named arguments and optional parameters have made it easier to construct immutable type instances though - you can still get many of the benefits of object initializers, without the mutability drawbacks. Simply provide default values for aspects of your type which are truly optional, leave the rest as mandatory constructor parameters, and the caller can do what they want - using named arguments to add clarity.

Collection initializers are a tougher nut to crack, unfortunately. I'd like to see "chained" initializers which could work with immutable collections, so that instead of repeatedly calling Add on the same instance, the compiler could create calls to Plus which chained together:

ImmutableList<string> x = new ImmutableList<string> { "a", "b", "c" };

would go to:

ImmutableList<string> x = new ImmutableList<string>().Plus("a")
                                                     .Plus("b")
                                                     .Plus"(c");

Of course, it would be nice to have more immutable collections in the framework to start with :)

None of this helps on the auto-props side, of course. I have to admit I've been cheating a certain amount recently, faking immutability using private setters:

public string Name { get; private set; }

It does make me feel dirty though, not making it truly immutable when that's my real intention.

Basically, I'm saying that I feel your pain - and I'm pretty sure the C# team does. Bear in mind they have limited resources though, and designing a language is darned hard.

You may find the videos from NDC 2010 interesting - there's a great panel discussion with Eric Lippert, Mads Torgersen, Neal Gafter (and me), and my proposals for C# 5 are in another video.

Oscillator answered 3/9, 2010 at 23:6 Comment(5)
It would certainly be nice if immutability was made easier. To guarantee full immutability, you have to be completely in control of all the classes you contain. For example, you said that anonymous types are immutable, however I added an array and a mutable list to it, and was able to modify both of them. If you have a publicly accessible member that is immutable today, it can be made mutable tomorrow, and your immutability gets broken as a result.Salem
Thx, I'll take a look at those videos. After reading some more it seems F# are dealing with these things in a nicer way, locking down objects by default and allowing mutability if the need is there. I guess legacy stops the c# team going in that direction. What are your thoughts about F# vs C# Jon?Trichinize
@TT: I haven't had as much experience as I'd like in F#, but I do like various things that F# does, certainly. Many of the suggestions I've made about C# 5 were based on F#.Oscillator
I agree 100% with you on private setters. It's far too easy for me to go propg+tab+tab rather than creating a proper readonly backing field. Surly public string Name { get; readonly set; } (as bizarre as that sounds) will make it into C# 5?Retractor
@Alex: That's exactly what I've proposed before now :) I don't know whether it'll get into C# 5 though. Hopefully we'll start to see the first bits in a little while.Oscillator
M
1

I remove all setters and only add the back if the property clearly need a setter. I find this makes my classes more robust and elegant OO wise

I completely agree with you. I faced with legacy code where there are a lot of object initializers used for some class hierarchy. I needed to add some properties and then I got a headache with finding all places where class instances are constructed. First time I submitted to. And now I need to add one more property. This is crazy!

To restrict usage of object-initializers I deleted parameterless constructor.

Mendicity answered 26/7, 2012 at 8:56 Comment(0)
R
0

I find constructors are very underused generally in c# code examples and I think auto-properties and object initializer are a big part of this

If your object has a lot of properties, you clearly don't want to initialize them all from the constructor. Having to pass more than, say, 4 or 5 parameters is pretty bad for readability (even though Intellisense makes it easy to write). Also, if you only want to initialize a few properties and use the default value for other properties, you either need many constructor overloads, or you have to pass these default values explicitly to the constructor.

In such cases object initializers are very handy, as long as the properties are not read-only (but as Jon pointed out, optional parameters in C# 4 are a good alternative)

why does the c# team push features like this and not is focusing more on deliver features pushing best practices more

I think object initializers were introduced because they were necessary for Linq: you couldn't create anonymous types without them. As for auto-properties, they're less vital, but it was probably easy to implement and it can be a real time saver for properties that do nothing more than encapsulating a field.

Reinstate answered 4/9, 2010 at 0:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.