将一个对象列表添加到其自身?

6

我在想,如果我把一个列表加到它自己上面会发生什么。也许会溢出堆栈,也许会出现编译器错误?

List<object> lstobj = new List<object>();
lstobj.Add(lstobj);

我执行了代码并检查了本地变量:

本地变量

这个列表似乎包含无限数量的列表实例。为什么没有栈溢出?这些列表只是指向原始列表的指针吗?但即使是指针,指针也会占用内存,不是吗?


2
我猜这只是在添加对自身的引用,所以当您进行检查时,您会一遍又一遍地看到相同的列表 :) 但从内存方面来看,它只是一个带有引用的列表。 - Fredrik Widerberg
指针确实占用内存 - 它是一个指向内存中某个位置的整数/长整数。但C#会隐藏它是整数/长整数这一事实,因为它知道它是在引用你的列表。 - MineR
它正在向自身添加一个引用。尝试添加更多,比如100000000个,看看是否会发生堆栈溢出异常。 - Tony
2个回答

3
不会有问题。List是引用类型,也就是说你会得到一个指向列表本身的引用(就像你所展示的那样)。因此,你在Visual Studio中看到的那个大层次结构只是表象。实际情况是:你得到了指向同一内存地址的数组内存地址的引用。因此,你会得到堆栈溢出。
在使用Entity Framework时,在导航属性中经常会遇到这种情况。
如果你尝试在没有配置序列化程序以在序列化循环引用时进行处理的情况下对列表进行序列化,那么就会出现问题。

2
取决于序列化器及其设置。例如,内置的DataContractSerializer具有记住和保留引用的选项,并允许对象的循环图。 - Scott Chamberlain
@ScottChamberlain,感谢您的评论,我已经修改了答案。 - Mohammed Noureldin

0

定义如下:

Line 1) object[] arr = new object[4];
Line 2) arr[0] = arr;

arr[0]现在是arr的另一个别名,arrarr[0]都具有相同的值,即数组数据的地址。

内存状态可能如下所示:

执行第1行代码后:

Address Value
@100:   104    // arr variable
@104:   0      // cell[0] of array data
@108:   0      // cell[1] of array data
@112:   0      // cell[2] of array data
@116:   0      // cell[3] of array data

在第二行之后:
Address Value
@100:   104    // arr variable
@104:   104    // cell[0] of array data
@108:   0      // cell[1] of array data
@112:   0      // cell[2] of array data
@116:   0      // cell[3] of array data

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接