【发布时间】:2015-04-22 17:12:07
【问题描述】:
您不能将 this 作为参数传递给基本构造函数 - 参见例如 C# language specification section 10.10.1 Constructor initializers(页面最后一行)。
我不明白这个限制,我愿意。在 C# 中,与 C++ 不同,正在构造的实例已经是它的实际类型并且“一切正常”(当然不是一切都被初始化;我的意思是在派生类的构造函数中调用的虚函数执行派生类的方法)。即使派生类的覆盖将被执行并且派生类可能还没有准备好,基类也可以调用自己的虚拟方法;这不排除。那么这个限制的原因是什么?
(在 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) {}
};
(在你抱怨我应该以不同的方式做这个例子之前,我的实际代码有点复杂 - 一个专门的稀疏数组 - 我有我的理由。)我将使用工厂的列表(以及工厂方法前往添加元素)来避免这种情况,这可以说是更好的设计,但我很困惑这种其他合理的方法被取缔了。
【问题讨论】:
-
您正在传递对未初始化对象的引用。完全有太多可能的事故,语言禁止它。
-
@Hans:它不是未初始化的:在调用实例构造函数之前,所有字段都有其分配的值(由于变量初始化器)或默认值(section 10.10.3)(事实使它与 C++ 不同)。在实例构造函数完成运行之前,实例可能不会语义初始化 - 但是当基类构造函数调用在派生类中重写的虚拟方法时没关系。
-
在这里争论的意义何在?与 C# 语言设计者交谈。
-
@Hans:对不起,我不是故意的。它认为我在我要求原因的问题中说得很清楚,所以我可以理解。我认为还有很多关于 SO 的其他问题,询问以各种语言做出选择背后的动机。
标签: c# constructor