嵌套 class - 这不是一个不完整的类型吗
Nested class - isn't this an incomplete type
示例代码:
public class SimpleClass
{
private NestedClass nestedClass = new NestedClass();
public class NestedClass : SimpleClass
{
}
}
// when instantiating in say.. main()
SimpleClass simpleClass = new SimpleClass();
我有 C++ 背景,所以我很难理解这里发生的事情。具体如何在SimpleClass
中实例化NestedClass
。由于理想情况下,编译器需要 SimpleClass
的完整布局才能实例化 NestedClass
,而这又需要 SimpleClass
。它本质上有点递归。
这就是我们 运行 这段代码时发生的情况。我们得到一个 Whosebug
:) 异常!
在 C++ 世界中,编译器在这种情况下会叫“incomplete type
”。
所以我的问题的关键是:
这是怎么回事,编译器是怎么布局的class(我知道它的实现细节,但是没有完整的类型我们怎么实例化一个对象?)
这个运行时间异常是故意的,还是应该是编译时错误?
它是一个嵌套 class 的事实在这里无关紧要。它是 derived class 的事实更为重要。除了关于泛型和访问的细节(例如,嵌套 classes 可以访问包含 class 的私有成员),嵌套 class 和非嵌套 [=57] 之间的区别相对较小=].
所以让我们证明:
class BaseClass
{
DerivedClass derived = new DerivedClass();
}
class DerivedClass : BaseClass
{
}
这仍然可以编译,如果您尝试创建 BaseClass
(或 DerivedClass
)的实例,仍然会失败并显示 WhosebugException
。
布局 很好:BaseClass
有一个字段,它是对 DerivedClass
的引用。就知道 "how big" 或 BaseClass
或 DerivedClass
而言没有问题 - 实际上没有初始化方面,这绝对没问题。这里重要的是DerivedClass
是一个引用类型,所以derived
字段的值是只是一个引用。
这里没有违反 C# 语言规则,设计一种语言规则来禁止这种情况而不禁止有效用例将非常困难。
这里的递归实际上与您可以用单个 class:
做的事情没有什么不同
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
示例代码:
public class SimpleClass
{
private NestedClass nestedClass = new NestedClass();
public class NestedClass : SimpleClass
{
}
}
// when instantiating in say.. main()
SimpleClass simpleClass = new SimpleClass();
我有 C++ 背景,所以我很难理解这里发生的事情。具体如何在SimpleClass
中实例化NestedClass
。由于理想情况下,编译器需要 SimpleClass
的完整布局才能实例化 NestedClass
,而这又需要 SimpleClass
。它本质上有点递归。
这就是我们 运行 这段代码时发生的情况。我们得到一个 Whosebug
:) 异常!
在 C++ 世界中,编译器在这种情况下会叫“incomplete type
”。
所以我的问题的关键是:
这是怎么回事,编译器是怎么布局的class(我知道它的实现细节,但是没有完整的类型我们怎么实例化一个对象?)
这个运行时间异常是故意的,还是应该是编译时错误?
它是一个嵌套 class 的事实在这里无关紧要。它是 derived class 的事实更为重要。除了关于泛型和访问的细节(例如,嵌套 classes 可以访问包含 class 的私有成员),嵌套 class 和非嵌套 [=57] 之间的区别相对较小=].
所以让我们证明:
class BaseClass
{
DerivedClass derived = new DerivedClass();
}
class DerivedClass : BaseClass
{
}
这仍然可以编译,如果您尝试创建 BaseClass
(或 DerivedClass
)的实例,仍然会失败并显示 WhosebugException
。
布局 很好:BaseClass
有一个字段,它是对 DerivedClass
的引用。就知道 "how big" 或 BaseClass
或 DerivedClass
而言没有问题 - 实际上没有初始化方面,这绝对没问题。这里重要的是DerivedClass
是一个引用类型,所以derived
字段的值是只是一个引用。
这里没有违反 C# 语言规则,设计一种语言规则来禁止这种情况而不禁止有效用例将非常困难。
这里的递归实际上与您可以用单个 class:
做的事情没有什么不同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