C#:为什么我不能将 'this' 作为构造函数参数传递给基 class?

C#: Why can't I pass 'this' as a constructor argument to a base class?

您不能将 this 作为参数传递给基本构造函数 - 请参见 C# language specification section 10.10.1 Constructor initializers(页面最后一行)。

我不明白这个限制,但很想了解。在 C# 中,与 C++ 不同,正在构造的实例已经是它的实际类型并且 "everything works"(当然不是所有的东西都被初始化;我的意思是在派生的 class 构造函数中调用的虚函数执行派生的 class' 方法)。基础 classes 被允许在其自身上调用虚拟方法,即使派生的 class' 覆盖将被执行并且派生的 class 可能还没有准备好;不排除这种可能性。那么这个限制的原因是什么?

(在 C++ 中,出于三个原因允许这样做。首先,用户或派生 class 应该知道他在做什么。其次,C++ 的用户应该知道他在做什么.第三,即使用户不知道他在做什么,C++ 哲学是给他上吊所需的绳子,然后在他打结时为他提供便利。我实际上喜欢那个哲学!)

顺便说一句,我想做的是在循环链表中构造正确初始化的列表成员。有一个基 class Element 和一个字段 Link 指向下一个元素。有一个 class 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 上添加元素的方法)来避免这种情况,这可以说是更好的设计,但我很困惑,这种其他合理的方法是非法的。

C# 和 .NET 的设计旨在让基础 class 能够控制其不变量。一旦 base-class 构造函数完成,derived-class 代码(包括 derived-class 构造函数)就可以操作对象的 base-class 部分基地 class 允许的任何方式。除了在 base-class 构造函数调用之前将值存储到它自己的(派生类型)字段之外,派生 class 不能对正在构造的对象做任何事情,但是 base class 契约实际上可以说 "I'm going to call this virtual method during my constructor, and any legitimate derived class must be prepared to deal with that".

该设计确实存在一些限制。恕我直言,最糟糕的是,在派生-class构造代码访问其构造函数参数后,没有任何机制可以让基class随时断言对构造过程的控制。

C# 在链接到基础构造函数之前计算字段初始化表达式,理论上这将允许派生的-class 对象在基础构造函数调用它们的虚拟方法之前设置自己;这样做的结果是字段初始化器表达式不能对正在构造的对象做任何事情。 VB.NET 运行 基础构造函数之后的初始化器,这允许更方便的访问,但意味着如果基础构造函数调用任何虚拟方法,字段将被初始化。就个人而言,我认为 C# 方法 "almost" 有用,但无法处理 class 其不变量会受到构造函数参数影响的问题严重限制了它的实用性。

顺便说一句,我真正希望看到的是 Object 包含一个虚拟方法,该方法将 运行 在最派生的构造函数完成执行或抛出异常之间时间控制 returns 到调用 foo = new Bar(); 的代码。 base-class 构造函数在 derived-class 构造函数到达 运行 之前暴露正在构造的对象的主要原因是没有标准的方法可以确保它们永远得到之后控制。这样的设计将大大改善构造函数的排序。不过,我不会为这样的事情屏住呼吸。