示例代码:
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在这种情况下哭泣.
所以我的问题的关键是:
这里发生了什么,编译器如何布局这个类(我知道它的实现细节,但没有完整的类型我们如何实例化一个对象?)
此运行时异常是故意的,还是应该是编译时错误?
这是一个嵌套类的事实在这里无关紧要.它是派生类的事实更为重要.除了泛型和访问的详细信息(例如,可以访问包含类的私有成员的嵌套类),嵌套类和非嵌套类之间的差异相对较小.
所以让我们说明:
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)