C# 列表在添加元素或创建副本后是否保存对元素的引用?

标签 c# list reference-type

假设我在创建时将一个对象添加到列表中,它是在列表中创建该对象的副本还是创建新对象,请考虑以下代码:

var obj = new A();
obj.Prop = 10;
var list = new List<A>() { obj };
foreach (var l in list) {
  l.Prop = 20;
}
Console.WriteLine(obj.Prop);

控制台会打印出什么内容?

最佳答案

答案是肯定和否定。

该列表将包含引用的副本。所以它会指向内存中的同一个对象。除非您在任何这些变量上分配对不同对象的引用或 null,否则它们将继续指向同一事物。

为了避免这种情况,您通常必须转到 into cloning 。与 Java 不同,它没有框架功能。

有两种情况不需要克隆:

  1. 内置基元类型
  2. 内置字符串类型(尽管是引用类型)

内置基元类型将其值复制到内存中的新位置。*

字符串在设计上又是不可变的。对于类来说,这是一种罕见的属性,因为在整个 .NET Framework 中甚至很难找到十几个 Inmutable。但在用户定义的类中,这种情况的可能性更大。

对于自制结构,我们甚至鼓励也将其设为不可变。

*除非 JiT 和编译器优化认为它似乎未得到充分利用,因此可以被删除。

关于C# 列表在添加元素或创建副本后是否保存对元素的引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58877619/

相关文章:

string - 方案 - 字符串附加错误类型以应用错误

kotlin - Kotlin 有原始类型吗?

c# - 如何在 rowdatabound 事件的 GridView 中检查状态(真/假)?

c# - 如何在不使用按位运算符的情况下避免短路操作

python - 如何以简单的单行方式打印列表中的元素?

go - 将一个引用类型为 "slice"的变量赋值给另一个变量,为什么它们不同时变化?

c++ - 如果在没有 new 运算符的情况下初始化,C++ 是否将类对象视为值类型?

c# - 使用长行标记增强 WPF 文本框?

c# - 对流使用 Close 而不是 Dispose 的原因?

python - 使用 itertools 在 python 中列出列表(仅移动 2 个项目,排列)