c# - 嵌套类——这不是一个不完整的类型吗

标签 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++ 背景,所以我很难理解这里发生的事情。具体来说,我们如何在 SimpleClass 中实例化 NestedClass。由于理想情况下,编译器需要 SimpleClass 的完整布局才能实例化 NestedClass,而后者又需要 SimpleClass。它本质上有点递归。

这就是我们运行这段代码时发生的情况。我们得到一个 StackOverflow :) 异常!

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

所以我的问题的关键是:

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

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

最佳答案

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

那么让我们证明:

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

class DerivedClass : BaseClass
{
}

这仍然可以编译,但仍然会失败并返回 StackOverflowException如果您尝试创建 BaseClass 的实例(或 DerivedClass )。

布局很好:BaseClass有一个字段,它是对 DerivedClass 的引用.知道“多大”也没有问题BaseClassDerivedClass是 - 实际上没有初始化方面,这绝对没问题。这里重要的是 DerivedClass是引用类型,所以 derived 的值字段只是一个引用。

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

这里的递归实际上与您可以对单个类执行的操作没有什么不同:

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

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


怀疑您正在考虑的问题很容易用结构证明,尽管不涉及继承:

struct Tweedledum
{
    Tweedledee dee;
}

struct Tweedledee
{
    Tweedledum dum;
}

确实失败了,因为没有合适的布局:Tweedledum值包含 Tweedledee直接值(value),反之亦然。不是引用:实际值。

这里的错误是:

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

关于c# - 嵌套类——这不是一个不完整的类型吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51909238/

相关文章:

c# - 如何在 XDocument.Load(string uri) 上设置超时?

.net - 在 System.Reflection 中使用 Moles

c# - .NET:值类型继承 - 技术限制?

javascript - jQuery 的 `$(this)` 为什么以及如何引用正确的节点?

c# - .NET MVC Linq -> XML RSS 阅读器 : Twitter XML Parsing Error

Python 字符串实习

c# - 以编程方式将事件分配给 FormView 中的子项

c# - 按类型查找 WPF 窗口中的所有控件

c# - 如何下载并运行.exe文件c#

c# - 使用linq对xml文件进行排序