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; } }
当我想将数据分配给一个types为Album
的对象时,接下来的两种方法有什么区别:
通过构造函数
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; } }
如果这个类是这样定义的,那就意味着在构造完成之后,修改类的内容并不是一个简单的方法。 不变性有好处。 当某些东西是不变的时候,确定它是正确的更容易。 毕竟,如果施工后不能修改,就没有办法做到“错”(一旦你确定它的结构是正确的)。 当你创build匿名类时,比如:
new { Name = "Some Name", Artist = "Some Artist", Year = 1994 };
编译器会自动创build一个不可变的类(也就是说,匿名类在构造之后不能被修改),因为不变性是有用的。 正因为如此,大多数C ++ / Java风格指南经常鼓励使成员成为const
(C ++)或final
(Java)。 移动部件较less时,更大的应用程序更容易validation。
所有人都说,有些情况下,你想快速修改你的class级结构。 比方说,我有一个工具,我想build立:
public void Configure(ConfigurationSetup setup);
我有一个class,有一些成员,如:
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... }
当我想configuration某些属性组合时,使用对象初始值设定项语法非常有用,但并不是一次性地全部configuration它们 。 例如,如果我只想configurationName
和Location
,我可以这样做:
ConfigurationSetup setup = new ConfigurationSetup { Name = "Some Name", Location = "San Jose" };
这允许我设置一些组合,而不必为每个可能的排列定义一个新的构造函数。
总的来说,我认为让你的类不可变将在很大程度上为你节省大量的开发时间,但是使用对象初始化语法使设置某些configuration排列变得更容易。
第二种方法是C#中的对象初始值设定项
对象初始值设定项可让您在创build时将值分配给对象的任何可访问字段或属性, 而无需显式调用构造函数 。
第一种方法
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;
为什么它使用临时对象(在debugging模式下)由Jon Skeet 在这里回答。
就两种方法的优点而言,如果你不想初始化所有的字段,那么IMO,对象初始值设定器会更容易使用。 就性能差异而言,我不认为会有任何对象初始化程序调用参数less构造函数,然后分配属性。 即使有性能差异,它应该是微不足道的。