嵌套类-这不是不完整的类型

时间:2018-08-18 13:36:57

标签: c# .net internals

示例代码:

public class SimpleClass
{
    private NestedClass nestedClass = new NestedClass();

    public class NestedClass : SimpleClass          
    {

    }
}

// when instantiating in say.. main()
SimpleClass simpleClass = new SimpleClass();

我来自C ++的背景,所以我很难理解这里发生的事情。具体来说,我们如何在NestedClass中实例化SimpleClass。由于理想情况下,编译器将需要SimpleClass的完整布局才能实例化NestedClass,而后者又需要SimpleClass。本质上是递归的。

这就是我们运行此代码时发生的情况。我们收到StackOverflow :)异常!

在C ++世界中,在这种情况下,编译器会哭“ incomplete type”。

所以我的问题的关键是:

  1. 这是怎么回事,编译器如何布局此类(我知道其实现细节,但是如果没有完整的类型,我们如何实例化对象?)

  2. 此运行时异常是故意的还是应该是编译时错误?

1 个答案:

答案 0 :(得分:6)

它是嵌套类的事实在这里无关紧要。它是一个派生的类这一事实更为重要。除了有关泛型和访问的详细信息(例如,嵌套类可以访问包含类的私有成员)之外,嵌套类和非嵌套类之间的区别相对较小。

所以让我们证明一下:

class BaseClass
{
    DerivedClass derived = new DerivedClass();
}

class DerivedClass : BaseClass
{
}

如果您尝试创建StackOverflowException(或BaseClass)的实例,它仍然可以编译,并且仍然失败,并显示DerivedClass

布局很好:BaseClass有一个字段,它是对DerivedClass的引用。就知道BaseClassDerivedClass的“大小”而言,这没有问题-实际上,如果没有初始化方面,那将是绝对好的。这里重要的是DerivedClass是引用类型,因此derived字段的值是 just 引用。

这里没有违反C#语言规则的情况,设计一个禁止不使用有效用例的语言规则将非常困难。

实际上,这里的递归与单个类的递归没有什么不同

class BaseClass
{
    BaseClass other = new BaseClass();
}

同样,它是完全有效的代码,但会导致堆栈溢出。


我想想的问题很容易通过结构来说明,尽管不涉及继承:

struct Tweedledum
{
    Tweedledee dee;
}

struct Tweedledee
{
    Tweedledum dum;
}

失败,因为没有适当的布局:Tweedledum值直接包含一个Tweedledee值,反之亦然。没有参考:实际值。

这里的错误是:

error CS0523: Struct member 'Tweedledum.dee' of type 'Tweedledee' causes a cycle in the struct layout
error CS0523: Struct member 'Tweedledee.dum' of type 'Tweedledum' causes a cycle in the struct layout