120

Supposing I have an Album class :

public class Album 
{
    public string Name {get; set;}
    public string Artist {get; set;}
    public int Year {get; set;}

    public Album()
    { }

    public Album(string name, string artist, int year)
    {
        this.Name = name;
        this.Artist = artist;
        this.Year = year;
    }
}

When I want to assign data to an object of type Album, what is the difference between the next 2 approaches :

Via Constructor

var albumData = new Album("Albumius", "Artistus", 2013);

or when instantiating

var albumData = new Album 
                    {
                         Name = "Albumius",
                         Artist = "Artistus",
                         Year = 2013
                    };
one noa
  • 345
  • 1
  • 3
  • 10
VasileF
  • 2,856
  • 2
  • 23
  • 36
  • 7
    possible duplicate of [What's the difference between an object initializer and a constructor?](http://stackoverflow.com/questions/740658/whats-the-difference-between-an-object-initializer-and-a-constructor) – Nikhil Agrawal Oct 02 '13 at 13:39
  • for one in the constructor you could be assigning a value to a private member variable while with object initializers you can only go with public properties – terrybozzio Oct 02 '13 at 13:42
  • Your constructor forces you to pass name, artist & year. They're optional for your object initiator. – Carra Oct 02 '13 at 13:43
  • If your constructor has some logic to construct your object and it needs some parameters to use in construction, than object initializer may not fit your need. But in 'YOUR displayed' case is not different. Object initializers are really done for unnamed objects in for Linq, so the atomic object can be created. Basically, the answer is, Sometimes it is different and sometimes it is not different. – T.S. Oct 02 '13 at 13:44
  • If you have a `struct` direct assignment of properties is much faster than constructor call. Make sure your struct is immutable though. – John Alexiou Jan 11 '16 at 20:55

3 Answers3

145

Both approaches call a constructor, they just call different ones. This code:

var albumData = new Album 
                {
                     Name = "Albumius",
                     Artist = "Artistus",
                     Year = 2013
                };

is syntactic shorthand for this equivalent code:

var albumData = new Album();
albumData.Name = "Albumius";
albumData.Artist = "Artistus";
albumData.Year = 2013;

The two are almost identical after compilation (close enough for nearly all intents and purposes). So if the parameterless constructor wasn't public:

public Album() { }

then you wouldn't be able to use the object initializer at all anyway. So the main question isn't which to use when initializing the object, but which constructor(s) the object exposes in the first place. If the object exposes two constructors (like the one in your example), then one can assume that both ways are equally valid for constructing an object.

Sometimes objects don't expose parameterless constructors because they require certain values for construction. Though in cases like that you can still use the initializer syntax for other values. For example, suppose you have these constructors on your object:

private Album() { }
public Album(string name)
{
    this.Name = name;
}

Since the parameterless constructor is private, you can't use that. But you can use the other one and still make use of the initializer syntax:

var albumData = new Album("Albumius")
                {
                     Artist = "Artistus",
                     Year = 2013
                };

The post-compilation result would then be similar to:

var albumData = new Album("Albumius");
albumData.Artist = "Artistus";
albumData.Year = 2013;
David
  • 208,112
  • 36
  • 198
  • 279
  • 1
    About the first two examples; it might be interesting to note that these will not be identical after compilation if the reference to the created object is stored in a field or global instead of a local variable. When an exception occurs in a property setter, then in one case the field will be set and in the other one not. This type of thing can be important when dealing with disposable objects and CA2000. – Wim Coenen May 04 '16 at 13:51
  • 1
    This might be late, but, please look at [this question](https://stackoverflow.com/questions/49662556/thread-safe-construction-with-attribute-assignment) caused by this answer. You should fix this answer – Camilo Terevinto Apr 05 '18 at 01:09
34

Object initializers are cool because they allow you to set up a class inline. The tradeoff is that your class cannot be immutable. Consider:

public class Album 
{
    // Note that we make the setter 'private'
    public string Name { get; private set; }
    public string Artist { get; private set; }
    public int Year { get; private set; }

    public Album(string name, string artist, int year)
    {
        this.Name = name;
        this.Artist = artist;
        this.Year = year;
    }
}

If the class is defined this way, it means that there isn't really an easy way to modify the contents of the class after it has been constructed. Immutability has benefits. When something is immutable, it is MUCH easier to determine that it's correct. After all, if it can't be modified after construction, then there is no way for it to ever be 'wrong' (once you've determined that it's structure is correct). When you create anonymous classes, such as:

new { 
    Name = "Some Name",
    Artist = "Some Artist",
    Year = 1994
};

the compiler will automatically create an immutable class (that is, anonymous classes cannot be modified after construction), because immutability is just that useful. Most C++/Java style guides often encourage making members const(C++) or final (Java) for just this reason. Bigger applications are just much easier to verify when there are fewer moving parts.

That all being said, there are situations when you want to be able quickly modify the structure of your class. Let's say I have a tool that I want to set up:

public void Configure(ConfigurationSetup setup);

and I have a class that has a number of members such as:

class ConfigurationSetup {
    public String Name { get; set; }
    public String Location { get; set; }
    public Int32 Size { get; set; }
    public DateTime Time { get; set; }

    // ... and some other configuration stuff... 
}

Using object initializer syntax is useful when I want to configure some combination of properties, but not neccesarily all of them at once. For example if I just want to configure the Name and Location, I can just do:

ConfigurationSetup setup = new ConfigurationSetup {
    Name = "Some Name",
    Location = "San Jose"
};

and this allows me to set up some combination without having to define a new constructor for every possibly permutation.

On the whole, I would argue that making your classes immutable will save you a great deal of development time in the long run, but having object initializer syntax makes setting up certain configuration permutations much easier.

Trent
  • 335
  • 2
  • 8
sircodesalot
  • 11,231
  • 8
  • 50
  • 83
  • @siercodesalot, Thank you for your answer. But I don't think specifying only some of the properties in object initializer, is the best argument. Because, just like that, in the constructor you can use default values and skip specifying a property. – VasileF Oct 02 '13 at 14:12
  • Take a look at `AppDomainSetup` (http://msdn.microsoft.com/en-us/library/system.appdomainsetup.aspx), which is used to configure new application domains. Would you really want to have a constructor that has 20 different properties - especially when you only want to actually define one or two? Secondly, default values don't really work if you only want to configure properties at the end of the constructor list (but not the beginning). – sircodesalot Oct 02 '13 at 14:14
  • Do not get me wrong, I am familiar with object initializer a lot, and it's useful and quick way. I wanted to know if there's any difference like performance or best practice, or cons/pros. You can explicitly specify in the constructor the parameter to define. For example, supposing I had all the constructor parameters with specified default value, I could rearrange them in the list as I'd want to : `var album = new Album(year: 2013, artist: "Artistus)`. Of course, it's more inconvenient work. Or you meant something else with end/beginning? – VasileF Oct 02 '13 at 14:33
  • 1
    That's a good point, while you *can* rearrange the order of the parameters, at a certain point the constructor gets so long that it stops making sense when you have the option of just using object initializers. That said, the primary reason *not* to use object initializers really boils down to situations where you want to enforce invariants through the constructor. For example, it's impossible to do functional style (immutable) programming with object-initialization because your property setters must be public. If there was one main tradeoff, immutability would probably be it. – sircodesalot Oct 02 '13 at 14:47
  • You say that "the compiler automatically create an immutable class" if the class is anonymous. But let's say I populate a list with anonymous classes, then I can still refer to them and change their properties right? – Essej Aug 24 '17 at 07:22
  • @Bartex - Try it out! – sircodesalot Aug 24 '17 at 13:10
  • If a property is only set in the constructor, you can remove `private set;` altogether. – Andrew Arthur Dec 04 '20 at 07:21
15

Second approach is object initializer in C#

Object initializers let you assign values to any accessible fields or properties of an object at creation time without having to explicitly invoke a constructor.

The first approach

var albumData = new Album("Albumius", "Artistus", 2013);

explicitly calls the constructor, whereas in second approach constructor call is implicit. With object initializer you can leave out some properties as well. Like:

 var albumData = new Album
        {
            Name = "Albumius",
        };

Object initializer would translate into something like:

var albumData; 
var temp = new Album();
temp.Name = "Albumius";
temp.Artist = "Artistus";
temp.Year = 2013;
albumData = temp;

Why it uses a temporary object (in debug mode) is answered here by Jon Skeet.

As far as advantages for both approaches are concerned, IMO, object initializer would be easier to use specially if you don't want to initialize all the fields. As far as performance difference is concerned, I don't think there would any since object initializer calls the parameter less constructor and then assign the properties. Even if there is going to be performance difference it should be negligible.

Community
  • 1
  • 1
Habib
  • 219,104
  • 29
  • 407
  • 436
  • 2
    I think part of the question is - 'Is it a good thing to bypass constructors?'. Are there benefits (flexibility) or drawbacks (bypassing the constructor logic, speed perhaps?) – guymid Oct 02 '13 at 13:40
  • 4
    The constructor isn't bypassed. The parameterless constructor will be used. – Ralf Oct 02 '13 at 13:41
  • Yea well, that's what I wanted actually, to mean... Is there an advantage over the other? Is there one having better performance over the other? Stuff like that (cons and pros) – VasileF Oct 02 '13 at 13:43
  • Remember that all objects in the absence of an explicit constructor will automatically implement the default parameterless constructor. If you include a constructor that has a parameter, then you must explicitly implement a parameterless one. If you try to use the syntax above (i.e. `new Album { params }`) when you have no default constructor, it will result in a compile time error - essentially you are always calling a constructor and an object initialiser is just syntactic sugar for setting properties/fields after instantiation – Charleh Oct 02 '13 at 13:44
  • @Charleh, that is indeed a very good point, but since the OP has a parameter less constructor, object initializer works. – Habib Oct 02 '13 at 13:47
  • @Habib and Ralf, I mean that part of the discussion of this subject should be (in my mind anyway) that any specific constructors with parameters are bypassed and you might have essential logic in your constructors. In Vasile Marian Fălămaș's example imagine there was an important bit of logic in the parameterised contructor. To the calling code both calls appear the same, but only the constructor one will execute the important code. – guymid Oct 02 '13 at 13:53
  • @guymid, I don't know how good that design would be, The main point with object initializer is that the **parameter less** constructor would be called, regardless of any other existing constructors. – Habib Oct 02 '13 at 13:57
  • 1
    @guymid ... and parametrized constructors doing logic that can be simply bypassed by calling the parameterless constructor would be a code smell. – Ralf Oct 02 '13 at 13:58
  • @Habib Yes, that's my point. By using the object initializer any logic in an equivalent constructor is bypassed and this might not be desired, or intentional from a novice developer – guymid Oct 02 '13 at 13:59