过载“基础” 构造函数或“this” 构造函数?
我有一些从简化的 Base
派生的类型,如下所示。
我不确定在重载构造函数时是否使用基类的构造函数或 this
构造函数。
ConcreteA
纯粹使用 base
构造函数重载构造函数,而ConcreteB
重载使用 this
进行前两个重载。
重载构造函数的更好方法是什么?
public abstract class Base
{
public string Name { get; set; }
public int? Age { get; set; }
protected Base() : this(string.Empty) {}
protected Base(string name) : this(name, null) {}
protected Base(string name, int? age)
{
Name = name;
Age = age;
}
}
public class ConcreteA : Base
{
public ConcreteA(){}
public ConcreteA(string name) : base(name) {}
public ConcreteA(string name, int? age) : base(name, age)
{
}
}
public class ConcreteB : Base
{
public ConcreteB() : this(string.Empty, null){}
public ConcreteB(string name): this(name, null){}
public ConcreteB(string name, int? age) : base(name, age)
{
}
}
[编辑] 看起来伊恩·奎格利在他的答案中所建议的似乎有意义。 如果我要进行初始化验证器的调用,则在以下情况下,ConcreteA(string)
将永远不会初始化验证器。
public class ConcreteA : Base
{
public ConcreteA(){}
public ConcreteA(string name) : base(name) {}
public ConcreteA(string name, int? age) : base(name, age)
{
InitializeValidators();
}
private void InitializeValidators() {}
}
I have few types that derive from simplified Base
as shown below.
I am not sure whether to use base class's constructor or this
constructor when overloading constructors.
ConcreteA
overloads constructors purely using base
constructors, whileConcreteB
overloads using this
for the first two overloads.
What would be a better way of overloading constructors?
public abstract class Base
{
public string Name { get; set; }
public int? Age { get; set; }
protected Base() : this(string.Empty) {}
protected Base(string name) : this(name, null) {}
protected Base(string name, int? age)
{
Name = name;
Age = age;
}
}
public class ConcreteA : Base
{
public ConcreteA(){}
public ConcreteA(string name) : base(name) {}
public ConcreteA(string name, int? age) : base(name, age)
{
}
}
public class ConcreteB : Base
{
public ConcreteB() : this(string.Empty, null){}
public ConcreteB(string name): this(name, null){}
public ConcreteB(string name, int? age) : base(name, age)
{
}
}
[Edit]
It looks like what Ian Quigley has suggested in his answer seemed to make sense.
If I were to have a call that initialize validators, ConcreteA(string)
will never initialize validators in following case.
public class ConcreteA : Base
{
public ConcreteA(){}
public ConcreteA(string name) : base(name) {}
public ConcreteA(string name, int? age) : base(name, age)
{
InitializeValidators();
}
private void InitializeValidators() {}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
这个。 因为如果您将代码放置在 ConcreteB(string, int?) 中,那么您希望仅使用字符串构造函数来调用它。
This. Because if you ever place code in ConcreteB(string, int?) then you want the string only constructor to call it.
一般来说,我会称之为“this”而不是“base”。 如果您稍后扩展您的类,您可能会以这种方式重用更多代码。
In general, I'd call "this" rather than "base". You'll probably reuse more code that way, if you expand your classes later on.
混搭就好; 最终,当您使用
this(...)
构造函数时,它将最终到达调用base(...)
的 ctor第一的。 在需要时重用逻辑是有意义的。您可以安排它,以便所有构造函数都调用一个公共(可能是私有)
this(...)
构造函数,该构造函数是唯一调用base(...)< /code> - 但这取决于 a: 这样做是否有用,以及 b: 是否有一个
base(...)
ctor 可以让你这样做。It is fine to mix and match; ultimately, when you use a
this(...)
constructor, it will eventually get to a ctor that callsbase(...)
first. It makes sense to re-use logic where required.You could arrange it so that all the constructors called a common (maybe private)
this(...)
constructor that is the only one that calls down to thebase(...)
- but that depends on whether a: it is useful to do so, and b: whether there is a singlebase(...)
ctor that would let you.就您的情况而言,从您提供的内容来看,这并不重要。 当当前类中有一个不属于基类的构造函数,或者当前类构造函数中有一些您想要执行的代码时,您实际上只想使用
this
不包含在基类中。In your case from what you have provided it doesn't matter. You really only want to use
this
when you have a constructor in your current class that is not part of your base class, or if there is some code in the current class constructor that you want to execute that isn't contained in the base class.为了降低代码路径的复杂性,我通常尝试只调用一个
base()
构造函数(ConcreteB
情况)。 这样您就知道基类的初始化总是以相同的方式发生。但是,根据您覆盖的类,这可能是不可能的,或者会增加不必要的复杂性。 这对于特殊的构造函数模式来说是正确的,例如实现 可序列化。
In order to reduce the complexity of the code paths, I usually try to have exactly one
base()
constructor call (theConcreteB
case). This way you know that the initialization of the base class always happens in the same fashion.However, depending on the class you override, this may not be possible or add unneeded complexity. This holds true for special constructor patterns such as the one when implementing ISerializable.
再问问自己为什么要重载 Base 类中的构造函数? 这一个就足够了:
子类也是如此,除非您在实例化时需要任一字段具有特定值,但在您的示例中并非如此,因为您已经有了默认构造函数。
还要记住,任何构造函数都应该将对象的实例置于正确的状态。
Ask yourself again why you are overloading the constructor in the Base class? This one is enough:
Same goes for the subclass unless you need either fields to have a particular value when you instantiate which in your example is not the case since you already have the default constructor.
Also remember that any constructor should put the instance of the object in a correct state.