为什么更新列表中的实例会更新另一个列表中的同一实例
本文关键字:实例 列表 更新 为什么 另一个 | 更新日期: 2023-09-27 17:56:25
我有一个类。
public class abc
{
public int i = 0;
public string a = "";
}
====
=======================================现在,我在abc类类型的列表中插入了一些记录
List<abc> c = new System.Collections.Generic.List<abc>();
abc a = new abc();
a.a = "1";
a.i = 1;
c.Add(a);
a = new abc();
a.a = "1";
a.i = 2;
c.Add(a);
====
===============================================创建列表变量并添加一些筛选的记录。
List<abc> temp = new System.Collections.Generic.List<abc>();
temp.AddRange(c.Where(i => i.i == 1));
===
============================================================================================================================================查询 = 通过执行以下代码行也将更改 c 变量。
我知道两者都指向相同的内存位置。有没有办法修复此代码?
foreach (abc d in temp)
{
d.i = 10;
}
它不是"为什么更新列表会更新另一个列表?
它是"为什么更新列表中的实例会更新另一个列表中的同一实例?
因为您使用的是此类的class
和相同的实例。
List<abc> list1 = new List<abc>();
list1.Add(new abc()); // new abc() creates an instance of the abc() class. Let's call this instance myInstance
List<abc> list2 = new List<abc>();
list2.Add(list1[0]); // Here you add the same instance (ie. myInstance) to the list2
list1[0].a = 5; // You modify the instance myinstance
Console.WriteLine(list2[0].a); // Returns "5" (because it is always the same instance myIsntance)
要避免此行为,您有 2 种解决方案:
创建一个克隆方法以克隆具有相同值的 abc 实例。
public class abc
{
public int i = 0;
public string a = "";
public abc Clone(abc instanceToClone)
{
abc result = new abc();
result.i = instanceToClone.i;
result.a = instanceToClone.a;
}
}
或者用结构替换类(那么你有一个值类型,但你不能有字段初始值设定项)
public struct abc
{
public int i; // Initialized by default to 0
public string a; // Initialized by default to null
}
我建议您阅读这篇出色的文章,以了解 C# 的"基本"概念。(不是那么容易,但真的很重要)
在需要时创建对象的克隆。例如,如果i
和a
是属性 - 它们完全应该是!——你可以写
temp.AddRange(c.Where(i => i.i == 1).Select(o => new abc { a = o.a, i = o.i}));
对对象实例所做的更新对该实例的每个所有者都是可见的。无论位于多少集合对象,或者包含它的类型集合,更改都将在任何地方可见。这仅仅是因为集合仅指向内存中的同一位置。无论您在哪里进行更改,它都将随处可见。
如果您需要避免此类行为,您有 2 个选择:
- 克隆一个集合中的对象
- 使用
struct
而不是class
public struct abc
{
int i;
string a;
}
abc a, b;
...
a.i = 1;
b = a;
/* new memory location is allocated for `b`, and values are copied from `a`.
therefore, updates made to `a` will not affect `b`*/
b.i = 2;
if (a.i == b.i)
throw new Exception("i values are same");