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

假设我有一个 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;
}
}

当我想将数据分配给 Album类型的对象时,下面两种方法之间的区别是什么:

通过构造器

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

在实例化时

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

第二种方法是 C # 中的对象初始化程序

对象初始值设定项允许您将值分配给任何可访问的字段或 在创建时对象的属性 < strong > 而不必 显式调用构造函数 .

第一步

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

显式调用构造函数,而在第二种方法中,构造函数调用是隐式的。使用对象初始值设定项也可以省略一些属性。比如:

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

对象初始值设定项可以转换为类似如下内容:

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

为什么它使用一个临时对象 (调试模式)是由 Jon Skeet 回答 给你

就这两种方法的优点而言,如果你不想初始化所有的字段,那么 IMO,对象初始化器会更容易使用。就性能差异而言,我认为不会有任何差异,因为对象初始化器调用参数 less 构造函数,然后分配属性。即使存在性能差异,也应该可以忽略不计。

这两种方法都调用了构造函数,只是调用了不同的构造函数:

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 几乎一模一样 after compilation (close enough for nearly all intents and purposes). So if the parameterless constructor wasn't public:

public Album() { }

那么无论如何都不能使用对象初始化程序。如果对象公开了两个构造函数(就像你的例子中的一个) ,那么可以假设这两种方法对于构造一个对象同样有效。

有时对象不公开无参数构造函数,因为它们为构造提供某些值。不过在这种情况下,您仍然可以对其他值使用初始值设定项语法。例如,假设您的对象上有这些构造函数:

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

因为无参数构造函数是私有的,所以不能使用它。但是您可以使用另一个并且仍然使用初始化器语法:

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

汇编后的结果将与下列结果相同:

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

对象初始化器很酷,因为它们允许您内联设置类。代价是你的类不可能是不可变的。考虑一下:

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;
}
}

如果类是这样定义的,那就意味着在构造完成之后,要修改类的内容并不容易。不变性也有好处。当某些东西是不可变的时候,很多更容易确定它是正确的。毕竟,如果它在构建之后不能被修改,那么它就永远不可能是“错误的”(一旦你确定它的结构是正确的)。创建匿名类时,如:

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

编译器将自动创建一个不可变类(也就是说,匿名类在构造之后不能被修改) ,因为不可变性非常有用。大多数 C + +/Java 风格指南经常鼓励使用成员 const(C + +)或 final(Java)。当移动部件较少时,更大的应用程序更容易验证。

总而言之,在某些情况下,您希望能够快速修改类的结构。假设我有一个想要设置的工具:

public void Configure(ConfigurationSetup setup);

我有一个类,它有许多成员,比如:

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

当我想配置属性的 一些组合,但是 不一定是一次性的时,使用对象初始化器语法是有用的。例如,如果我只想配置 NameLocation,我可以这样做:

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

这允许我设置 some combination,而不必为 每个可能的排列定义一个新的构造函数。

总的来说,从长远来看,使您的类不可变将为您节省大量的开发时间,但是拥有对象初始化器语法使得设置某些配置排列变得更加容易。