C# : assign data to properties via constructor vs. instantiating

159,147

Solution 1

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 identical to:

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

Solution 2

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.

Solution 3

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.

Share:
159,147

Related videos on Youtube

VasileF
Author by

VasileF

Updated on July 21, 2020

Comments

  • VasileF
    VasileF almost 4 years

    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
                        };
    
    • Nikhil Agrawal
      Nikhil Agrawal over 10 years
    • terrybozzio
      terrybozzio over 10 years
      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
    • Carra
      Carra over 10 years
      Your constructor forces you to pass name, artist & year. They're optional for your object initiator.
    • T.S.
      T.S. over 10 years
      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.
    • John Alexiou
      John Alexiou over 8 years
      If you have a struct direct assignment of properties is much faster than constructor call. Make sure your struct is immutable though.
  • guymid
    guymid over 10 years
    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?)
  • Ralf
    Ralf over 10 years
    The constructor isn't bypassed. The parameterless constructor will be used.
  • VasileF
    VasileF over 10 years
    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)
  • Charleh
    Charleh over 10 years
    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
  • Habib
    Habib over 10 years
    @Charleh, that is indeed a very good point, but since the OP has a parameter less constructor, object initializer works.
  • guymid
    guymid over 10 years
    @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.
  • Habib
    Habib over 10 years
    @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.
  • Ralf
    Ralf over 10 years
    @guymid ... and parametrized constructors doing logic that can be simply bypassed by calling the parameterless constructor would be a code smell.
  • guymid
    guymid over 10 years
    @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
  • VasileF
    VasileF over 10 years
    @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.
  • sircodesalot
    sircodesalot over 10 years
    Take a look at AppDomainSetup (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).
  • VasileF
    VasileF over 10 years
    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?
  • sircodesalot
    sircodesalot over 10 years
    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.
  • Wim Coenen
    Wim Coenen about 8 years
    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.
  • Essej
    Essej almost 7 years
    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?
  • sircodesalot
    sircodesalot almost 7 years
    @Bartex - Try it out!
  • Camilo Terevinto
    Camilo Terevinto about 6 years
    This might be late, but, please look at this question caused by this answer. You should fix this answer
  • Andrew Arthur
    Andrew Arthur over 3 years
    If a property is only set in the constructor, you can remove private set; altogether.