【问题标题】:C#: When adding the same object to two List<object> variables, is the object cloned in the process?C#:将同一个对象添加到两个 List<object> 变量时,该对象是否在进程中被克隆?
【发布时间】:2009-06-05 18:13:04
【问题描述】:

我有类似的东西:

// Declarations:
List<SomeType> list1 = new List<SomeType>();
List<SomeType> list2 = new List<SomeType>();

...

SomeType something = new SomeType("SomeName");
list1.Add(something);
list2.Add(something);

...

list1[indexOfSomething] = new SomeType("SomeOtherName");

list2 中的对象并没有改变...这是预期的结果吗?

【问题讨论】:

    标签: c# collections


    【解决方案1】:

    是的,但没有克隆任何内容。在分配之前,同一个对象在两个列表中。分配后,您在两个列表中有两个唯一的对象。

    这样做:

    list1[indexOfSomething].name = "SomeOtherName";
    

    list2 中的对象也会发生变化。

    【讨论】:

    • 假设 SomeType 是一个接口,我的目标是将对象更新为继承接口的不同类(与上面的代码不同,因为您无法实例化接口 - 尽管技术性除外) ,唯一的方法是在两个列表中找到对象并用新对象替换它们吗?还是有其他巧妙的办法?
    • “聪明”的方法是拥有一些实现接口的包装器类型并委托给实现相同接口的成员。将包装器放在两个列表中,然后您可以更新包装器仅在一个位置保存的对象,两个列表都将获得更新。
    【解决方案2】:
    // Declarations:
    List<SomeType> list1 = new List<SomeType>();
    List<SomeType> list2 = new List<SomeType>();
    
    ...
    
    SomeType something = new SomeType("SomeName");
    list1.Add(something);
    list2.Add(something);
    

    请记住,当您将对象添加到列表时,您实际上只是添加了指向该对象的指针。在这种情况下,list1 和 list2 都指向内存中的同一个地址。

    list1[indexOfSomething] = new SomeType("SomeOtherName");
    

    现在您已将元素 list1 分配给不同的指针。

    您并没有真正克隆对象本身,而是复制恰好指向同一个对象的指针。如果您需要证明,请执行以下操作:

    SomeType something = new SomeType("SomeName");
    list1.Add(something);
    list2.Add(something);
    
    list1[someIndex].SomeProperty = "Kitty";
    
    bool areEqual = list1[someIndex].SomeProperty == list2[someIndex].SomeProperty;
    

    areEqual 应该是真的。指针摇滚!

    【讨论】:

      【解决方案3】:

      您没有克隆对象;您正在两个列表中添加对同一对象的引用。但是,您的代码将其中一个列表中的引用替换为对另一个对象的引用,所以是的,这是预期的行为。

      【讨论】:

        【解决方案4】:

        您正在将一个列表中的引用替换为对新对象的引用。如果您要更改该对象的属性,您会看到它在两个地方都发生了变化,因为引用将保持不变。

        【讨论】:

          【解决方案5】:

          是的,您没有克隆对象。该对象最初是通过引用添加到两个列表中的,然后在列表中为您分配了对您正在创建的新对象的引用。

          这绝对是预期的结果。

          【讨论】:

            【解决方案6】:

            当您将“某物”对象传递给 Add 时,您是按值传递(c# 默认),而不是按引用传递

            【讨论】:

            • 我不认为这是正确的。您正在按值传递引用,但您仍在传递引用。在示例中,赋值重新分配了 list1 中的引用,这就是 list2 中的引用没有改变的原因。
            【解决方案7】:

            是的,这是预期的。仅添加对对象的引用。不是参考本身或副本。

            【讨论】:

              猜你喜欢
              • 2019-02-26
              • 2011-07-26
              • 2015-04-25
              • 1970-01-01
              • 1970-01-01
              • 2013-06-23
              • 2019-04-07
              • 2018-11-27
              • 1970-01-01
              相关资源
              最近更新 更多