8

我与一位在 C# 方面有多年经验的开发人员一起工作。我再也没有办法联系到他,我记得他说在默认参数少的构造函数中包含代码不是一个好主意,但我不记得原因。

在 C# 或任何语言的默认构造函数中包含代码是好的做法还是坏的做法?

4

9 回答 9

8

这取决于具体情况,但将代码放在默认构造函数中绝对不是坏习惯。如果需要,请继续执行。

于 2013-04-26T16:14:44.237 回答
6

这取决于情况,有时需要,有时可以使用,有时不应该存在。

重要的是任何构造函数都应该使对象处于正确初始化的状态。如果一个对象总是需要一些代码来初始化,但没有特定的输入来做到这一点,那么无参数的构造函数将是一个很好的地方。

于 2013-04-26T16:17:00.837 回答
5

想到的是 Effective Java 中的第 17 条(作者 Joshua Bloch):

第 17 项:设计和文件继承或禁止继承

他解释说,构造函数不应该调用可覆盖的方法:

public class Super {
    // Broken - constructor invokes an overridable method
    public Super() {
        overrideMe();
    }
    public void overrideMe() {
    }
}

最终发生的是您正在调用超类的构造函数(当您创建子类的实例时)并且您得到了意外的行为。

如果您的构造函数确实调用了类中的其他方法,则需要在 API 中记录这一点,以便开发人员对其进行子类化时,他们会知道会发生什么。

否则,将代码放入构造函数中没有任何害处。

于 2013-04-26T16:18:58.520 回答
2

由于您将 C# 与 .NET 框架一起使用。让我给你完整的 MSDN 的“构造函数设计”文章:

http://msdn.microsoft.com/en-us/library/vstudio/ms229060(v=vs.100).aspx

在我看来,您应该只将初始化代码放在构造函数中。

于 2013-04-26T16:17:50.500 回答
2

使用 BinaryFormatter 反序列化对象时,创建对象时不会运行默认构造函数。BinaryFormatter 使用一种技巧让 .NET 提供一个初始化实例,在该实例中不运行默认构造函数。

这不应该造成问题,因为 BinaryFormatter 自己填充了所有私有成员。我能想象的唯一危险的情况是,如果您使用默认构造函数将对象“注册”到其他静态类中的某个地方或类似的东西,在这种情况下,您会遇到一系列全新的问题。

于 2013-04-26T16:19:14.250 回答
2

经验法则

让它尽可能简单。

良好的编码标准的全部意义在于可维护性和可调试性。我们都遇到过意大利面条式的代码。这只是为了让其他人更好地理解您的 API。即使有好的 javadoc,大多数人也不希望构造函数改变应用程序状态。

例如,如果实例化您的对象会进行一些数据库操作,那么您最好有一个该死的好理由。

反例

你仍然需要做最好的事情。如果您决定使用延迟加载的单例来加载缓存或连接或您拥有的东西,那么重点是当您实例化它时它会自动加载某些东西。

于 2013-04-26T16:25:41.857 回答
0

我知道我们调用了默认构造函数中所有参数的初始化。有时我们需要在声明之外“清空”数据,所以我们在一个单独的方法中进行,并在任何对象的最低构造函数中调用它。

于 2013-04-26T16:15:17.723 回答
0

这是一个品味问题。我发现用户 kokos 定义的这些规则非常有用:

他的规则:

  1. 不要使用声明中的默认值(null、false、0、0.0...)进行初始化。
  2. 如果您没有更改字段值的构造函数参数,则首选在声明中进行初始化。
  3. 如果字段的值由于构造函数参数而更改,则将初始化放在构造函数中。
  4. 在你的练习中保持一致。(最重要的规则)

请参阅:在构造函数或声明中初始化类字段?

于 2013-04-26T16:17:14.400 回答
0

未初始化的类字段通常应该在默认构造函数中结束。如果您在声明的同一行初始化类字段,那么如果您反序列化此类对象,这些语句将不会运行。此外,在默认 ctor 中收集所有初始化是一种很好的做法。

于 2013-04-26T16:17:59.517 回答