当我第一次开始使用面向对象的编程语言时,我被教导了以下规则:
在类中声明字段时,不要初始化它。在构造函数中执行此操作。
C#中的一个例子:
public class Test
{
private List<String> l;
public Test()
{
l = new List<String>();
}
}
但是当有人最近问我为什么这样做时,我无法想出一个理由。 我并不熟悉C#(或其他编程语言)的内部工作原理,因为我相信这可以在所有OO语言中完成。
为什么 这样做了?安全吗?特性
答案 0 :(得分:14)
如果您有多个构造函数,则可能需要将字段初始化为不同的值
在构造函数中初始化字段时,对于何时根据构造函数的其余部分进行初始化,可能不会产生混淆。对于单个类来说,这似乎是微不足道的,但是如果你有一个继承层次结构,并且在每个级别运行构造函数代码并访问超类字段,那么这一点就不那么重要了。
答案 1 :(得分:10)
C#编译器将采用您内联的任何非静态成员初始化,并将其移动到构造函数中。换句话说:
class Test
{
Object o = new Object();
}
汇编到这个:
class Test
{
Object o;
public Test()
{
this.o = new Object();
}
}
我不确定其他语言的编译器如何处理这个问题,但就C#而言,这是一个风格问题,你可以自由地做任何你想做的事情。 请注意,静态字段的处理方式不同: read this article for more information on that。
答案 2 :(得分:2)
这样做的一个原因是它将所有初始化代码放在一个地方,方便其他人阅读你的课程。说完这个之后,我并不是出于两个主要原因。 (1)我使用TDD /单元测试来定义我的班级的行为。如果你想知道无参数构造函数的作用,你应该真正阅读我在无参数构造函数上构建的测试。 (2)使用C#3.0,我通常使用自动属性和带无参数构造函数的内联初始化来实例化对象。这样更灵活,它将属性的定义放在使用代码的位置。这会覆盖构造函数中的任何初始化,所以我很少把它放在那里。当然,这仅适用于C#。
实施例。 (2)
var foo = new Foo { Bar = "baz" };
public class Foo
{
public string Bar { get; set; }
public Foo() { }
}
答案 3 :(得分:1)
有时构造函数具有用于初始化内部变量的参数。例如数组的大小
答案 4 :(得分:0)
我没有听到一个令人信服的理由不提供两种选择。我怀疑真正的原因与从解析角度简化语言结构有关。在C衍生语言中尤其如此,其中解析赋值语句需要75%的语言语法规则。在我看来,允许它并定义它如何精确地工作将是很好的。我同意Michael's comment关于复杂性的增加,因为您插入继承和多个构造函数,但仅仅因为您添加了一个功能并不意味着您必须使用它。我会投票支持两者,即使我的投票并没有真正加起来。
答案 5 :(得分:0)
我总是喜欢将类视为对象的工厂,将构造函数视为生产线上的最终停止。在类中声明的字段是描述对象的蓝图,但是在通过调用构造函数来命令这样的对象之前,蓝图将不会被实现为对象...而且,正如有人指出的那样,在所有的初始化中执行你的构造函数将提高可读性,并且它将在初始化时提供动态性(它可能不是你正在处理的无参数构造函数)。
此外,在某些语言中,构造函数可用于将对象重置为原始状态,这就是为什么需要在构造函数中实例化对象的原因。