是列表<;T>;指针

本文关键字:指针 gt lt 列表 | 更新日期: 2023-09-27 18:11:48

我注意到List<T>的行为与其他简单对象不同,例如String。这个问题可能看起来很新鲜,但这确实让我印象深刻,因为我认为List<T>是简单的对象。

以以下代码为例:

List<String> ls1 = new List<String>();
ls1.Add("a");
List<String> ls2 = ls1;
ls1.Add("b");

最后,ls1将等于{"a", "b"}ls2也将等于。这与此代码的行为完全不同:

String s1 = "a";
String s2 = s1;
s1 = "b";

其中s1在末尾等于bs2等于a

这意味着List<T>实际上是一个指针,对吧?

是列表<;T>;指针

List<T>是一个引用类型,所以是的,它的行为就像一个指针。

String也是一个引用类型,但字符串是不可变的,在某些情况下,它们的行为类似于值类型(与引用类型相反(,因此您在这里感到困惑。

这里有一个很好的解释来解释为什么字符串以这种方式工作:在C#中,为什么字符串是一个行为类似于值类型的引用类型?

s1 = "b"实际上为s1分配了一个新的引用。CCD_ 16和CCD_。

ls1引用的对List<string>对象的更改通过对该对象的所有引用(包括ls2(可见。当你制作ls2 = ls1时,你基本上是说ls1ls2都引用了同一个对象。经由参考变量ls1对对象的改变经由参考变量ls2可见。

在C#中,它们被称为references,而不是pointers。也许它们是一样的,减去不能将它们强制转换为整数以打印它们的事实,再减去禁止的指针算术。从技术上讲,它们是"不透明的",所以你不应该知道它们是如何工作的。很明显,如果您使用托管C++:-(

,这种不透明性就会被打破

C#中的每个对象都是引用。像int、string、char这样的基本体不是引用。

String、int、float都是值类型。所以,当你说

String s1 = "a";
String s2 = s1;
s1 = "b";

初始化s2时,s1的值被复制到分配给s2的空间中。因此,如果您窥探内存,您可以在内存中的两个不同位置(分配给s1的位置和分配给s2的内存(找到"a"的十六进制表示。但是,如果你试图对引用类型做同样的事情,比如List,当你说这样的话时,会发生什么是一个传递引用:

List<String> ls1 = new List<String>();
ls1.Add("a");
List<String> ls2 = ls1;
ls1.Add("b");

是具有与堆上分配的List相对应的对象。查找该对象的地址位于为局部变量s1和s2分配的空间上,而不是位于该空间中的实际值。原因是对象(List(可能是一个很大的对象,并且可能在程序的整个生命周期中使用很长时间,并且为这样的对象从堆栈中分配内存会很昂贵。我建议您阅读这个问题线程,以了解CLR 如何真正解释值类型和引用类型