Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 嵌套类-isn';这不是不完整的类型吗_C#_.net_Internals - Fatal编程技术网

C# 嵌套类-isn';这不是不完整的类型吗

C# 嵌套类-isn';这不是不完整的类型吗,c#,.net,internals,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++

示例代码:

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
。它本质上有点递归

这就是我们运行代码时发生的情况。我们得到一个
堆栈溢出
:)异常

<>在C++世界中,编译器会在这种情况下大声叫喊“<代码>不完整类型< /代码>”。 所以我的问题的关键是:

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

    public class NestedClass : SimpleClass          
    {

    }
}

// when instantiating in say.. main()
SimpleClass simpleClass = new SimpleClass();
  • 这里发生了什么,编译器如何布局这个类(我知道它的实现细节,但没有完整的类型,我们如何实例化一个对象?)

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


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

    让我们展示一下:

    class BaseClass
    {
        DerivedClass derived = new DerivedClass();
    }
    
    class DerivedClass : BaseClass
    {
    }
    
    如果您尝试创建
    基类
    (或
    DerivedClass
    )的实例,此操作仍然会编译,并且仍然会失败,出现
    StackOverflowException

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

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

    这里的递归与使用单个类所能做的事情没有多大区别:

    class BaseClass
    {
        BaseClass other = new BaseClass();
    }
    
    同样,它是完全有效的代码,但会导致堆栈溢出


    我怀疑您正在考虑的问题很容易用structs演示,尽管不涉及继承:

    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
    

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

    让我们展示一下:

    class BaseClass
    {
        DerivedClass derived = new DerivedClass();
    }
    
    class DerivedClass : BaseClass
    {
    }
    
    如果您尝试创建
    基类
    (或
    DerivedClass
    )的实例,此操作仍然会编译,并且仍然会失败,出现
    StackOverflowException

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

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

    这里的递归与使用单个类所能做的事情没有多大区别:

    class BaseClass
    {
        BaseClass other = new BaseClass();
    }
    
    同样,它是完全有效的代码,但会导致堆栈溢出


    我怀疑您正在考虑的问题很容易用structs演示,尽管不涉及继承:

    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
    

    想象一下,<代码> SimpleClass < /C>包含指针<代码> NeStdByth*NeStdEds< /C>(不完全类型问题可以用C++来声明,使用前向声明和移动的东西)我从来没有使用过C++(甚至不能读取它),并且已经在.NET中工作了十多年了。我从没想过要写这样的代码。对我来说,这似乎太错误了,以至于我甚至想不出一个有效的用例(尽管可能有一些用例)。@Zoharpeld一个相关的用例是当使用NullObject模式时,尽管它使用静态字段。想象一下
    SimpleClass
    包含一个指针
    NestedClass*NestedClass
    (C++中的不完全类型问题可以通过使用前向声明和移动的方法来解决)我从来没有使用C++(甚至不能读取它),并且已经在.NET中工作了十多年了。我从来没有想过要写这样的代码。我觉得我甚至无法想象一个有效的用例。(尽管可能有一些人在那里)@ZoharPeled一个相关的用例是当使用NullObject模式时,尽管它使用静态字段。这很有意义!对于C/C++背景的人来说,简单来说,nestedClass更像一个*p_nestedClass,因此编译器只需要为它分配架构字大小。因此定义的类是一个完整的类型!这使得对于C/C++背景的读者来说,简单地说,nestedClass更像一个*p_nestedClass,因此编译器只需要为它分配架构字大小