C#:通过构造函数与实例化将数据分配给属性
本文关键字:数据 分配 属性 实例化 构造函数 | 更新日期: 2023-09-27 18:33:46
假设我有一个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
的对象时,接下来的 2 种方法有什么区别:
通过构造函数
var albumData = new Album("Albumius", "Artistus", 2013);
或在实例化时
var albumData = new Album
{
Name = "Albumius",
Artist = "Artistus",
Year = 2013
};
这两种方法都调用构造函数,它们只是调用不同的构造函数。 此代码:
var albumData = new Album
{
Name = "Albumius",
Artist = "Artistus",
Year = 2013
};
是此等效代码的语法简写:
var albumData = new Album();
albumData.Name = "Albumius";
albumData.Artist = "Artistus";
albumData.Year = 2013;
编译后,两者几乎相同(对于几乎所有意图和目的来说都足够接近(。 因此,如果无参数构造函数不是公共的:
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...
}
当我想配置某种属性组合时,使用对象初始值设定项语法很有用,但不一定一次配置所有属性组合。例如,如果我只想配置Name
和Location
,我可以做:
ConfigurationSetup setup = new ConfigurationSetup {
Name = "Some Name",
Location = "San Jose"
};
这允许我设置一些组合,而不必为每个可能的排列定义一个新的构造函数。
总的来说,我认为从长远来看,使您的类不可变将为您节省大量开发时间,但是使用对象初始值设定项语法可以更轻松地设置某些配置排列。
第二种方法是 C# 中的对象初始值设定项
对象初始值设定项允许您为任何可访问字段或 对象在创建时的属性,而不必 显式调用构造函数。
第一种方法
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,对象初始值设定项将更容易使用,特别是如果您不想初始化所有字段。就性能差异而言,我认为不会有任何差异,因为对象初始值设定项调用参数较少构造函数,然后分配属性。即使会有性能差异,也应该可以忽略不计。