C#:通过构造函数与实例化将数据分配给属性

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19138195/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 14:12:44  来源:igfitidea点击:

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

c#oopconstructorproperties

提问by VasileF

Supposing I have an Albumclass :

假设我有一个Album类:

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 :

当我想将数据分配给类型的对象时Album,接下来的两种方法有什么区别:

Via Constructor

通过构造函数

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

or when instantiating

或者在实例化时

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

采纳答案by David

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 identicalafter compilation. 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 requirecertain 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;

回答by Habib

Second approach is object initializer in C#

第二种方法是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 hereby Jon Skeet.

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.

就这两种方法的优点而言,如果您不想初始化所有字段,IMO,对象初始值设定项将更易于使用。就性能差异而言,我认为不会有任何差异,因为对象初始值设定项调用无参数构造函数然后分配属性。即使会有性能差异,它也应该可以忽略不计。

回答by sircodesalot

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 MUCHeasier 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.

编译器会自动创建一个不可变的类(即匿名类在构造后不能修改),因为不变性就是那么有用。出于这个原因,大多数 C++/Java 样式指南通常鼓励创建成员const(C++) 或final(Java)。当移动部件较少时,更大的应用程序更容易验证。

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 combinationof properties, but not neccesarily all of them at once. For example if I just want to configure the Nameand Location, I can just do:

当我想配置一些属性组合时,使用对象初始值设定项语法很有用,但不一定一次配置所有属性。例如,如果我只想配置Nameand Location,我可以这样做:

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

and this allows me to set up some combinationwithout having to define a new constructor for everypossibly 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.

总的来说,我认为从长远来看,让你的类不可变会为你节省大量的开发时间,但是拥有对象初始值设定项语法可以更容易地设置某些配置排列。