5

当我第一次开始使用面向对象的编程语言时,我被教导了以下规则:

在类中声明字段时,先不要初始化它。在构造函数中执行此操作。

C# 中的一个示例:

public class Test
{
    private List<String> l;

    public Test()
    {
        l = new List<String>();
    }
}

但是当最近有人问我为什么要这样做时,我想不出一个理由。我不太熟悉 C#(或其他编程语言,就此而言,因为我相信这可以在所有 OO 语言中完成)的内部工作原理。

那么为什么这样做呢?是安全吗?特性?

4

6 回答 6

14
  • 如果您有多个构造函数,您可能希望将一个字段初始化为不同的值

  • 当您在构造函数中初始化字段时,不会混淆它何时相对于构造函数的其余部分进行初始化。对于单个类,这可能看起来微不足道,但当您有一个继承层次结构时,构造函数代码在每个级别运行并访问超类字段时,情况就不那么重要了。

于 2009-03-26T12:44:53.067 回答
10

C# 编译器将采用您内联执行的任何非静态成员初始化并将其移动到您的构造函数中。换句话说:

class Test
{
    Object o = new Object();
}

被编译成这样:

class Test
{
    Object o;

    public Test()
    {
        this.o = new Object();
    }
}

我不确定其他语言的编译器如何处理这个问题,但就 C# 而言,这是一个风格问题,你可以随意做任何你想做的事情。 请注意,静态字段的处理方式不同: 阅读本文以获取更多信息

于 2009-03-26T12:43:29.233 回答
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() { }
  }
于 2009-03-26T12:49:24.413 回答
1

有时构造函数具有用于初始化内部变量的参数。例如数组的大小

于 2009-03-26T12:46:15.983 回答
0

我还没有听到不提供两种选择的令人信服的理由。我怀疑真正的原因与从解析的角度简化语言结构有关。在解析赋值语句需要 75% 的语言语法规则的 C 派生语言中尤其如此。在我看来,允许它并定义它如何精确地工作会很好。我同意Michael关于插入继承和多个构造函数时复杂性增加的评论,但仅仅因为您添加了一个功能并不意味着您必须使用它。我会投票支持两者,即使我的投票并没有真正加起来。

于 2009-03-26T12:50:18.343 回答
0

我总是喜欢把类想象成对象的工厂,把构造函数想象成生产线上的最后一站。类中声明的字段是描述对象的蓝图,但是在通过调用构造函数对此类对象进行排序之前,蓝图不会被实现为对象......另外,正如有人指出的那样,在您的构造函数将提高可读性,并且它将提供初始化的动态性(它可能不是您正在处理的无参数构造函数)。

此外,在某些语言中,构造函数可用于将对象重置为原始状态,这就是为什么必须在构造函数中实例化对象的原因。

于 2009-03-26T13:31:05.093 回答