在声明时初始化类成员变量是否更好?
private List<Thing> _things = new List<Thing>();
private int _arb = 99;
或者在默认构造函数中?
private List<Thing> _things;
private int _arb;
public TheClass()
{
_things = new List<Thing>();
_arb = 99;
}
这只是风格问题,还是有性能方面的权衡取舍?
在声明时初始化类成员变量是否更好?
private List<Thing> _things = new List<Thing>();
private int _arb = 99;
或者在默认构造函数中?
private List<Thing> _things;
private int _arb;
public TheClass()
{
_things = new List<Thing>();
_arb = 99;
}
这只是风格问题,还是有性能方面的权衡取舍?
就性能而言,没有真正的区别;字段初始化器是作为构造函数逻辑实现的。唯一的区别是字段初始化器发生在任何“base”/“this”构造函数之前。
构造函数方法可与自动实现属性一起使用(字段初始化器不能)-即
[DefaultValue("")]
public string Foo {get;set;}
public Bar() { // ctor
Foo = "";
}
除此之外,我倾向于使用字段初始化程序语法;我发现它可以使事情更加局部化。
private readonly List<SomeClass> items = new List<SomeClass>();
public List<SomeClass> Items {get {return items;}}
我不必四处搜寻以找到它的分配位置...
显然的例外情况是当您需要执行复杂逻辑或处理构造函数参数时,在这种情况下,基于构造函数的初始化是最好的选择。同样,如果您有多个构造函数,最好始终以相同的方式设置字段-因此您可以使用以下构造函数:
public Bar() : this("") {}
public Bar(string foo) {Foo = foo;}
编辑:作为一个旁注,请注意,在上面的例子中,如果还有其他带有字段初始化器的字段(未显示),则它们仅在调用base(...)
的构造函数中直接初始化 - 也就是public Bar(string foo)
构造函数。另一个构造函数不运行字段初始化程序,因为它知道它们已经由this(...)
构造函数完成。
class
,每个构造函数都有一个隐式的 : base()
,除非你添加更具体的内容 - 这可能是 : base(123, "abc")
,也可能是 : this(123, "abc")
。 - Marc Gravell实际上,您展示的字段初始化器是一种方便的简写方式。编译器会将初始化代码复制到您为类型定义的每个实例构造函数的开头。
这有两个影响:首先,任何字段初始化代码在每个构造函数中都会重复出现;其次,您在构造函数中包含的任何代码以将字段初始化为特定值实际上都会重新分配这些字段。
因此,在性能和编译代码大小方面,将字段初始化程序移入构造函数中会更好。
另一方面,性能影响和代码“膨胀”通常可以忽略不计,并且字段初始化程序语法的重要好处是减少您可能会忘记在其中一个构造函数中初始化某些字段的风险。
使用字段初始化器或创建Init()函数。将这些内容放入构造函数中的问题在于,如果您需要添加第二个构造函数,则最终会出现复制/粘贴代码(或者您忽略它并最终得到未初始化的变量)。
我建议在声明时进行初始化。或者让构造函数调用一个Init()函数。
这完全取决于你。
我经常在行内初始化它们,因为当我不真正需要构造函数时,我不喜欢有一个(我喜欢小类!)。
关于上述的一个额外要点——在实现具有实现的类时,您总是会有一个构造函数。如果您没有声明,则编译器会推断出默认值 [public Foo(){}]; 即不带参数的构造函数。
通常我喜欢提供两种方法。允许构造函数用于那些希望使用它们的情况,并允许字段初始化器用于希望使用类/类型的简化或默认实现的情况。这为您的代码增加了灵活性。请记住,任何人都可以选择使用默认字段初始化程序...如果您提供多个构造函数,请务必手动声明 - public Foo(){}