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

后端 未结 3 1062
孤城傲影
孤城傲影 2020-12-22 19:04

Supposing I have an Album class :

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


        
相关标签:
3条回答
  • 2020-12-22 19:21

    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;
    
    0 讨论(0)
  • 2020-12-22 19:26

    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.

    0 讨论(0)
  • 2020-12-22 19:32

    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.

    0 讨论(0)
提交回复
热议问题