1

我有一堂课。

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));

================================================

Query = 通过执行以下代码行也将更改 c 变量。

我知道这两个点都指向同一个内存位置。有没有办法修复这个代码?

foreach (abc d in temp)
{
    d.i = 10;
}
4

3 回答 3

4

这不是“为什么更新列表会更新另一个列表?”

它是“为什么更新列表中的实例会更新另一个列表中的相同实例?”

因为您使用的是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 个解决方案:

创建一个 Clone 方法以克隆具有相同值的 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# 的“基本”概念。(不是那么容易但真的很重要)

于 2013-01-29T12:59:50.663 回答
3

随时创建对象的克隆。例如, ifiawere 属性——它们完全应该是!——你可以写

temp.AddRange(c.Where(i => i.i == 1).Select(o => new abc { a = o.a, i = o.i}));
于 2013-01-29T13:00:31.803 回答
0

对对象实例所做的更新对该实例的每个所有者都是可见的。无论位于多少个集合对象,或者包含什么类型的集合,变化都会随处可见。这仅仅是因为集合只指向内存中的相同位置。无论您在哪里进行更改,它都会随处可见。

如果您需要避免此类行为,您有两种选择:

  • 克隆一个集合中的对象
  • 使用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");
于 2013-01-29T13:08:58.103 回答