C# 在基类构造函数中构造对象?

C# 在基类构造函数中构造对象?,c#,oop,constructor,C#,Oop,Constructor,我目前有以下代码模式,我正在初始化一般类MyClass的构造函数中MyThing类型的特定对象。然而,在一些特定的派生类示例中(例如MySpecialClass),我想使用MyThing的派生版本,我称之为MySpecialThing public class MyClass { public MyClass() { this.MyThing = new MyThing(); } public MyThing MyThing { get; set

我目前有以下代码模式,我正在初始化一般类MyClass的构造函数中MyThing类型的特定对象。然而,在一些特定的派生类示例中(例如MySpecialClass),我想使用MyThing的派生版本,我称之为MySpecialThing

public class MyClass
{
    public MyClass()
    {
        this.MyThing = new MyThing();
    }

    public MyThing MyThing { get; set; }
}

public class MySpecialClass : MyClass
{
    public MySpecialClass()
    {
        this.MyThing = new MySpecialThing();
    }
}
我的问题是,这是否是一种不好的做法,因为实际上神话属性被初始化了两次,一次在基类中,一次在派生类中。显然,我可以将布尔值传递给基类构造函数或其他东西,告诉它不要费心初始化神话,但这可能太过分了…

使用受保护的:

class BaseClass
{
    protected SomeType MyThing;
}
使用受保护的:

class BaseClass
{
    protected SomeType MyThing;
}

这取决于创造神话的开销

但是,有一个解决方案:

您可以添加一个受保护的基类构造函数,该构造函数接受MyThing类型的参数,并在那里初始化它

public class MyClass
{
    private readonly MyThing myThing;

    public MyClass(): this(new MyThing())
    {
    }

    protected MyClass(MyThing thing)
    {
        Contract.Requires(thing != null);
        myThing = thing;
    }

    public MyThing MyThing { get { return myThing; } }
}

public class MySpecialClass : MyClass
{
    public MySpecialClass(): base(new MySpecialThing())
    {
    }
}
我认为这是一种比向公共基类构造函数添加bool更好的方法

我还认为,即使构建神话的开销很小,这也是值得的,因为它更清楚地表达了设计


我还稍微改变了设计,使
myThing
成为一个只读字段,以表达只应在构建时设置的意图。(如果情况并非如此,并且您希望以后可以对其进行设置,则必须恢复到公共属性设置程序。)

这取决于创建虚构的开销

但是,有一个解决方案:

您可以添加一个受保护的基类构造函数,该构造函数接受MyThing类型的参数,并在那里初始化它

public class MyClass
{
    private readonly MyThing myThing;

    public MyClass(): this(new MyThing())
    {
    }

    protected MyClass(MyThing thing)
    {
        Contract.Requires(thing != null);
        myThing = thing;
    }

    public MyThing MyThing { get { return myThing; } }
}

public class MySpecialClass : MyClass
{
    public MySpecialClass(): base(new MySpecialThing())
    {
    }
}
我认为这是一种比向公共基类构造函数添加bool更好的方法

我还认为,即使构建神话的开销很小,这也是值得的,因为它更清楚地表达了设计


我还稍微改变了设计,使
myThing
成为一个只读字段,以表达只应在构建时设置的意图。(如果情况并非如此,并且您希望以后可以对其进行设置,则必须恢复到公共属性设置程序。)

您关心的是性能还是可维护性

只有当
虚构
构造函数的成本很高,或者必须在紧循环中创建大量对象时,性能问题才有意义


我更担心可维护性,因为您有多个初始化对象状态的地方。您可以将其从派生类传递给受保护的基类构造函数,并拥有默认使用
虚构的默认构造函数
您关心的是性能还是可维护性

只有当
虚构
构造函数的成本很高,或者必须在紧循环中创建大量对象时,性能问题才有意义


我更担心可维护性,因为您有多个初始化对象状态的地方。您可以将其从派生类传递给受保护的基类构造函数,并拥有默认使用
虚构
的默认构造函数

您甚至可以在基类中委托默认构造函数:
public MyClass():this(new MyThing()){}
,但这只是一个意见问题:)总体而言,+1.回答很好,谢谢。让它成为只读的好主意。我通常是只读变量的爱好者,只是令人恼火的是,没有类似于{get;set;}符号的速记法来表示只读属性和字段。几年前,我确实向Microsoft Connect添加了一个“只读”属性的请求,但事实证明,由于存在一些语法和其他问题,实现起来不如我预期的那么简单。:)是的,我想目前唯一的获取值的方法是通过构造函数,很难定义“隐式”语法。他们可以改为允许在只读变量的构造函数上使用对象初始化器语法,不知道这是否会打开其他蠕虫。您甚至可以在基类中委托默认构造函数:
public MyClass():this(new MyThing()){}
,但这只是一个意见问题:)总体而言,+1。回答很好,谢谢。让它成为只读的好主意。我通常是只读变量的爱好者,只是令人恼火的是,没有类似于{get;set;}符号的速记法来表示只读属性和字段。几年前,我确实向Microsoft Connect添加了一个“只读”属性的请求,但事实证明,由于存在一些语法和其他问题,实现起来不如我预期的那么简单。:)是的,我想目前唯一的获取值的方法是通过构造函数,很难定义“隐式”语法。他们可以允许在只读变量的构造函数上使用对象初始化器语法,但不知道这是否会打开其他蠕虫。