C# 在默认构造函数中包含代码的错误做法
我与一位开发人员一起工作,这位开发人员在C#方面比我年长很多年。我再也没有办法联系他了,我记得他说在默认的无参数构造函数中包含代码不是一个好主意,但我记不起原因了C# 在默认构造函数中包含代码的错误做法,c#,oop,C#,Oop,我与一位开发人员一起工作,这位开发人员在C#方面比我年长很多年。我再也没有办法联系他了,我记得他说在默认的无参数构造函数中包含代码不是一个好主意,但我记不起原因了 在C#或任何语言的默认构造函数中包含代码是好的做法还是坏的做法?这取决于具体情况,但将代码放入默认构造函数绝对不是坏的做法。如果需要,请继续操作。我知道我们对默认构造函数中的所有参数进行了初始化调用。有时我们需要在声明之外“清空”数据,因此我们使用单独的方法,并在任何对象的最低构造函数处调用它。这取决于情况,有时需要,有时可以使用,有
在C#或任何语言的默认构造函数中包含代码是好的做法还是坏的做法?这取决于具体情况,但将代码放入默认构造函数绝对不是坏的做法。如果需要,请继续操作。我知道我们对默认构造函数中的所有参数进行了初始化调用。有时我们需要在声明之外“清空”数据,因此我们使用单独的方法,并在任何对象的最低构造函数处调用它。这取决于情况,有时需要,有时可以使用,有时不应该存在
重要的是,任何构造函数都应该使对象处于正确初始化的状态。如果一个对象总是需要一些代码来初始化,但没有特定的输入来初始化,那么无参数构造函数将是一个很好的地方。这是一个品味问题。我发现用户kokos定义的这些规则非常有用: 他的规则是:
在我看来,您应该只在构造函数中放入初始化代码。u初始化的类字段通常应该在默认构造函数中结束。如果在与声明相同的行上初始化类字段,则如果反序列化此类对象,这些语句将不会运行。此外,在默认ctor中收集所有初始化也是一种很好的做法。我想到的是来自有效Java的第17项(由Joshua Bloch编写): 第17项:继承或禁止的设计和文件 他解释说,构造函数不应调用可重写的方法:
public class Super {
// Broken - constructor invokes an overridable method
public Super() {
overrideMe();
}
public void overrideMe() {
}
}
最终发生的情况是,您正在调用超类的构造函数(当您创建子类的实例时),并获得意外的行为
如果您的构造函数调用了类中的其他方法,那么您需要在API中记录这些方法,这样当开发人员对其进行子类化时,他们就会知道会发生什么
否则,将代码放入构造函数中不会有任何伤害。当使用BinaryFormatter反序列化对象时,在创建对象时不会运行默认构造函数。BinaryFormatter使用一个技巧获取.NET以提供一个没有运行默认构造函数的初始化实例
这不应该造成问题,因为BinaryFormatter本身填充所有私有成员。我能想象的唯一危险的情况是,如果使用默认构造函数将对象“注册”到某个其他静态类中的某个位置,或者类似的东西中,在这种情况下,您会遇到一组全新的问题。经验法则 让它尽可能简单 好的编码标准的全部要点是可维护性和调试能力。我们都遇到过类似意大利面条的代码。这只是为了让其他人更好地理解您的API。即使使用良好的javadoc,大多数人也不希望构造函数改变应用程序状态 例如,如果实例化对象进行了一些数据库操作,那么最好有一个非常好的理由 反例
你仍然需要做最好的事情。如果您决定使用一个延迟加载的单例来加载缓存或连接或您所拥有的东西,关键是当您实例化它时,它将自动加载它。非常重要,构造函数不能抛出异常。如果初始化的任何部分可能抛出,请使用try/catch并处理它。@GalacticCowboy:相反,如果构造函数无法正确初始化对象,则应该抛出异常。这是构造函数阻止创建对象的唯一方法。比如说:啊,没错。我是基于对FxCop规则的记忆,但它实际上会引发静态构造函数-静态构造函数中的异常会导致整个应用程序域的类型被破坏。@GalacticCowboy:啊,这是有道理的。这将是一个不可追踪的例外情况。:)这不应该是个问题,因为如果不能通过反序列化创建类,您可以简单地避免将该类标记为可序列化的。@Guffa这不是问题所在。您可能不知道在反序列化时会发生这种情况。此外,如果确实需要,还可以实现IDeserializationCallback接口来参与此事件。但你需要知道,这是真的