views:

761

answers:

10

I was wondering, what is the preferred way to construct a new object in C#?

Take a Person class:

public class Person 
{
    private string name;
    private int age;

    //Omitted..
}

Should I create it to use:

New Person("name", 24);

or

New Person() { Name = "name", Age = 24 };

Is it just a matter of taste or is there a good reason to use one over the other?

I can imagine that one should only use the required fields in the constructor and optional fields not as constructor parameters but by using properties.

Am I right in that?

+2  A: 

The second way is just syntactic sugar for setting the properties manually:

Person p = new Person();
p.Name = "name";
p.Age = 24;

You're also not depending on the constructor which may not initalize all the properties you want to set.

If your class has a constructor which requires these two parameters, you don't get around to explicitly call that constructor.

VVS
+6  A: 

It really depends on the scenario. The property approach has a lot of convenience, in that you don't have to duplicate the assignments in the constructor. Furthermore, most data-binding scenarios like to be able to create new objects, for which they usually use the parameterless constructor, so that is a big advantage.

However, for immutable types, the constructor approach is the only sensible option. Interestingly (perhaps) the named/optional parameters in C# 4.0 allow something similar to object initalizers for immutable types - see here.

The constructor approach is also very popular for Inversion of Control frameworks, as it clearly advertises what that class needs in order to function.

You may need to mix and match, but usually more property-style than constructor-style.

Marc Gravell
Yes - readonly fields can only be set by constructor code.
Dario
+4  A: 

Setting the values in the constructor, makes those properties mandatory, so this means you cannot create a new instance, without settings those properties. In some situations this is preferable, in other situations this is not prefferable.

Frederik Gheysels
This is true, although for structs you cannot of course make setting mandatory.
Noldorin
Indeed, but that's because a struct is a value type, and always has a (default) value, even if it is not initialized.
Frederik Gheysels
A: 

My main considerations on this question are 1) How much data will the instantiating entity have when the object is instantiated and 2) How encapsulated does the class need to be? If, once set, the properties shouldn't be able to change (at least, due to any outside entities) then I would use the constructor, since the constructor can set any read-only properties as well as any read/write properties.

Also remember that, just like any other method, your Constructor can be overloaded, so you can set up any number of ways to initialize those properties.

In general, I use constructors, but there are times when I set the properties manually instead. Use the right tool for the right problem.

AllenG
+4  A: 

I always work on the basis that you should pass values to a constructor which are mandatory for that object to exist in a valid state.

In you example you could say that new person cannot exists without an age so that should be passed in to the contructor.

If you work on the basis that an object should model a real work entity then that determines the minimum necessary to make any object valid - whether you set those as default values or by passing values in via the constructor.

BarneyHDog
+1: Objects should always be left in a valid state after construction and after each method call, so methods don't have to validate their own object's state before running, only their arguments.
palm3D
+2  A: 

In my opinion, you should first decide what makes a person a person. What are the person's properties for a person object to be correctly instantiated. What are the minimum requirements for a person.

There should always be a constructor with the minimum requirements.

I would only use object initializers for types that don't require any properties to be instantiated. Hence the default constructor.

I know that object initializers are very convenient. Other mechanisms also might require an empty constructor in the object.

But I don't think that it makes a lot of sense that you could create a Person without a name.

bruno conde
+3  A: 

A few thoughts:

  1. You need public properties to use Object Initializers. So if there's something you don't want to expose, you have to initialize them by constructor parameter.

  2. If you check IL, you will find Object Initializer is not "atomic". If you write code like this (not that I recommend, just an examle):

    using (p = New Person() {Name = GetName(), Age = GetAge()}) { //blah, blah }

If there's an exception in GetAge(), you will create a instance of Person in corrupted state. Worse, you can never enter the using scope and that instance will not be disposed as you would imagine.

Kai Wang
+17  A: 

The preferred way depends on your design.

Constructor properties are for items that your object requires in order to be correctly constructed. That is to say, any properties the object should have in order to be initialized need to be in the constructor (you don't usually want a partially intialized object after the constructor is called unless you're creating a factory or builder pattern and the constructor is hidden from all but the factory/builder).

Property intializers are best for additional configuration after a constructor that is required by your particular use case but is not required for the object to be considered initialised.

For example, you could have an object that represents a person. A person needs a name and an age to be initialised, but the address they live at is an optional configuration. So, the name and age are constructor parameters, and the address is a read/write property.

Person johnDoe = new Person("John Doe", 24) { Address = "42 Adams Street" };
Jeff Yates
that's a very nice rationale that helps to discern when to apply what. Thanks!
Peterdk
A: 

For settings the properties manually, they would have to be declared public, and you may want the class members to be private. In which case the constructor is the way to go, or write methods to get/set them or use an accessor. -Brian

BrianK
A: 

I tend to prefer a very simple constructor with property intializers. I find it leads to more explicit code. The only data I would pass to the constructor is information that I do not want the user of my class to alter once the class is created.

Terenced