c#类将彼此作为成员包含

本文关键字:成员 包含 | 更新日期: 2023-09-27 17:50:49

我有两个c#类A, b。

代码是这样的

Class A
{
     B object1;
     bool x;
}
Class B       
{     
    A object2;        
    bool y;
}

这可能吗?如果是,这意味着什么?A有B的对象B有A的对象....

c#类将彼此作为成员包含

在父/子关系等结构中,这确实是可能的,并且在许多情况下是理想的。你甚至可以让一个类的成员属于同一个类(就像在层次树中一样)。

但是你不能拥有的是:

class A : B
{
    //Implementation of A
}
class B : A
{
    //Implementation of B
}

这可能是混淆的根源,因为编译器将无法分辨哪个是基类,哪个是派生类。

这可能吗?

当然,这是可能的——你可以通过编译来确认。

如果是,这是什么意思?A有B的对象B有A的对象....

要理解这一点,您需要理解值类型(struct)和引用类型(class)之间的区别。

你可以把结构体想象成一块普通的内存。struct中的所有字段都是一个接一个地放置的。如果其中一些字段也是结构体,那么该"子"结构体的所有字段都应该放在"父"结构体的普通内存块中,依此类推。因此,当您声明值类型变量时,您确切地知道这种结构体的每个字段将如何在一个内存块中对齐。对于struct不可能有你提到的情况,当A有B的字段,B有A的字段等。

引用类型(类)是不同类型的东西。当使用引用类型的值进行操作时,实际上是使用对某个内存块的引用进行操作。您可以将引用(虽然不完全正确,但确实简化了事情)视为整数。当你使用引用类型变量时,不管它的类型是什么,你只是使用它的引用,一些int值。类成员本身在单独的内存块中创建。所以在你的例子中,所有的引用都是这样的:
A => B
B => A

或者像这样

A <=> B

这样的定义没有错,你有两个相互引用的对象,就像父对象知道它的子对象,而子对象知道它的父对象。

这是可能的,因为类A不应该保留类B的所有字段-它只具有对其他对象的引用(整数)。

CLR和编译器帮助你识别这些引用的类型,但基本上,类相互引用的情况与类引用其他类的情况相同。

结构和类之间的一个更重要的区别-当你声明值类型变量时,你实际上是创建它,为它保留内存等;当你声明引用类型变量时,你实际上是在创建引用,它将被初始化为null引用,因此无处引用。所以创建类A和类B的实例很容易——这些字段没有引用;但是创建这样的结构体A和B是不可能的,因为你必须一次创建所有的东西,这在有限的时间和内存下是不可能的。

和一个小实验来证明这一切。考虑两种情况。首先像问题中的那个:

    public class Class_A { public Class_B b; }
    public class Class_B { public Class_A a; }

编译时没有问题。

第二个与第一个类似,但使用结构体:

    public struct Struct_A { public Struct_B b; }
    public struct Struct_B { public Struct_A a; }

第一个编译没有问题,第二个错误:

CS0523: Struct member 'Struct_A. '类型'Struct_B'的b'导致结构布局中的循环

你将有循环/循环依赖

这是可能的,但是c#中类定义的关键字是class而不是Class

如果这两个类在不同的dll中,你会遇到很多与dll循环引用相关的问题(避免)。

您还创建了一个循环引用问题,如果您序列化(循环引用时使用XML序列化?)

在大多数情况下,
是一个有效且有用的定义。