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

sub*_*per 1 .net c# internals

示例代码:

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

    public class NestedClass : SimpleClass          
    {

    }
}

// when instantiating in say.. main()
SimpleClass simpleClass = new SimpleClass();
Run Code Online (Sandbox Code Playgroud)

我来自C++背景,所以我很难绕过这里发生的事情.具体来说我们如何实例化NestedClass内部SimpleClass.理想情况下编译器需要完全布局SimpleClass才能实例化NestedClass,而这又需要SimpleClass.它本质上是递归的.

这就是我们运行此代码时会发生的情况.我们得到StackOverflow:)例外!

在C++世界中,编译器会incomplete type在这种情况下哭泣.

所以我的问题的关键是:

  1. 这里发生了什么,编译器如何布局这个类(我知道它的实现细节,但没有完整的类型我们如何实例化一个对象?)

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

Jon*_*eet 6

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

所以让我们说明:

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

class DerivedClass : BaseClass
{
}
Run Code Online (Sandbox Code Playgroud)

StackOverflowException如果您尝试创建BaseClass(或DerivedClass)实例,它仍会编译,但仍会失败.

布局是精细:BaseClass具有单一字段,它是将一个参考DerivedClass.有没有在方面没有问题,知道"有多大"要么BaseClass或者DerivedClass是-事实上无需初始化方面,这将是绝对的罚款.这里重要的是它DerivedClass是一个引用类型,因此该derived字段的值只是一个引用.

这里没有破解C#语言规则,设计一个禁止这种情况而不禁止有效用例的语言规则真的很难.

这里的递归与单个类的功能没有什么不同:

class BaseClass
{
    BaseClass other = new BaseClass();
}
Run Code Online (Sandbox Code Playgroud)

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


尽管没有继承,但我怀疑你想到的问题很容易用结构体来证明:

struct Tweedledum
{
    Tweedledee dee;
}

struct Tweedledee
{
    Tweedledum dum;
}
Run Code Online (Sandbox Code Playgroud)

确实失败了,因为没有合适的布局:值直接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
Run Code Online (Sandbox Code Playgroud)