您无法将this
作为参数传递给基础构造函数 - 请参阅例如C# language specification section 10.10.1 Constructor initializers(页面的最后一行)。
我不明白这个限制,并希望如此。在C#中,与C ++相反,正在构造的实例已经处于其实际类型中并且"一切正常并且#34; (当然,并非所有内容都已初始化;我的意思是在派生类'构造函数中调用的虚函数执行派生类'方法)。允许基类在自己上调用虚方法,即使派生类是'将执行override并且派生类可能没有为它做好准备;这并不排除。那么这个限制的原因是什么?
(在C ++中允许这有三个原因。首先,用户或派生类应该知道他在做什么。其次,C ++的用户应该知道他在做什么。第三,即使用户并不知道他在做什么C ++的理念是给他一条绳子,让他自己上吊,然后在他打结时帮助他。我实际上喜欢那个哲学! )
顺便说一下,我尝试做的是在循环链接列表中构建正确初始化的列表成员。有一个基类Element
,其字段为Link
,指向下一个元素。有一个类Head
派生自Element
,它将成为列表开头的区分哨兵,并且对整个列表都有特殊行为。 Element
的构造函数将列表的头部作为参数,我想按如下方式编写以正确初始化元素和头部:
class Element {
protected Element link;
public Element(Element prior)
{
this.link = null;
prior.link = this;
}
};
class Head : Element {
public Head() : base(this) {}
};
(在你抱怨我应该以不同的方式做这个例子之前我的实际代码有点复杂 - 一个专门的稀疏数组 - 我有我的理由。)我将使用工厂列表(和工厂)为了避免这种情况,可以使用Head添加元素的方法,这可能是更好的设计,但我很困惑,这种其他合理的方法是非法的。
答案 0 :(得分:1)
C#和.NET的设计旨在为其不变量提供基类控制。完成基类构造函数后,允许派生类代码(包括派生类构造函数)以基类允许的任何方式操作对象的基类部分。派生类不能对正在构造的对象做任何事情,除了在基类构造函数调用之前将值存储到它自己的(派生类型)字段,但是基类契约实际上可以说" I'我将在构造函数中调用此虚方法,并且任何合法的派生类都必须准备好处理它"。
设计确实存在一些局限性。最糟糕的恕我直言,在派生类构造代码访问其构造函数参数之后,基类无法在任何时间断言对构造过程的控制。
C#在链接到基础构造函数之前计算字段初始化表达式,理论上这将允许派生类对象在基础构造函数调用其虚方法之前自行设置;这样做的结果是,字段初始化表达式无法对正在构造的对象执行任何操作。 VB.NET在基本构造函数之后运行初始化程序,这允许更方便的访问,但是如果基础构造函数调用任何虚方法,则意味着字段将被整合。就个人而言,我认为C#方法是"几乎"有用,但无法处理其不变量会受构造函数参数影响的类严重限制了它的用途。
我真正希望看到的是,顺便说一下,Object
将包含一个虚拟方法,该方法将在最派生的构造函数完成执行或抛出异常并且时间控制返回之间运行调用foo = new Bar();
的代码。基类构造函数在派生类构造函数运行之前公开构造中的对象的主要原因是它们没有标准的方法来确保它们之后能够获得控制权。这样的设计将极大地改进构造函数排序。不过,我并没有屏住呼吸。