【问题标题】:generic container in c# problem of modifying container elements outside the containerc#泛型容器在容器外修改容器元素的问题
【发布时间】:2011-03-18 03:10:36
【问题描述】:

我在 C# 编程中遇到问题,需要帮助, 当我在 c# 中创建一个通用容器并在列表之外修改它的一个元素时,它也被修改了,而我想保持列表的元素原样

我已经搜索了容器范围或引用,但我什么也没找到 顺便说一句,我之前多次遇到过这个问题,我用复制构造函数解决了如下

List<Object> list=new List<Object>();
list.Add(new Object(object) );

但在这种情况下,我的解决方案无效

 List<List<Object>> allObjects = new List<List<Object>>(1000);
 List<Object> object = new List<Object>();

 for (int i = 0; i < 1000; i++)
 {
            object = new List<Object>();
            //some code here that fill  object list
            allObjects.Add(object);

 }//after filling all the 1000 elements in allObjects list,all the elements of the   //list are 1000 elements with the same value of the last object has been inserted

我的错误解决方案对问题没有影响

 List<List<Object>> allObjects = new List<List<Object>>(1000);
 List<Object> object = new List<Object>();

 for (int i = 0; i < 1000; i++)
 {
            object = new List<Object>();
            //some code here that fill object list
            allObjects.Add(new List<Object>(object));

 }

提前致谢

【问题讨论】:

  • 您是否尝试复制对象列表而不保留原始对象引用,以便您可以编辑第二个列表(及其对象)而不影响第一个?
  • 我认为用 new 创建一个新的对象列表就足够了,还有其他方法可以释放以前添加的对象列表引用吗,谢谢
  • 我对你想要做什么感到有点困惑。代码看起来就像您正在创建一个空列表列表。我猜这不是你想要的。
  • 我正在创建一个列表列表,让我们命名内部列表 list1 和更大的列表(列表列表) list2,在一个循环中,我试图用一些数据填充 list1,并在 1 的末尾循环我在list2中插入list1 ...我的问题是虽然我在循环的每个开始都创建了新的空list1,list2元素受到更改list1元素的影响,并且在1000个循环结束时我得到了list2,其中包含1000个元素1000 个相同的 list1(添加的最后一个)...希望我已经解释清楚了

标签: c# generics scope containers


【解决方案1】:

C# 中的对象是引用类型。当您创建一个新对象时,.net 会在堆上为该对象分配内存,变量本身本质上是指向该对象的指针。

列表,“通用容器”,保存对对象的引用列表,而不是对象本身。当您从列表中获取对象时,即:var x = list[10],您实际上只是获得了对列表所引用的同一对象的引用。通过修改对象,更改也将反映在列表中包含的对象中。

要“修改列表外的对象”,并且不在列表内的对象上表示该更改,您必须复制该对象;有几种方法可以做到这一点,具体取决于您的对象到底是什么。

就本示例而言,如果您选择使用结构类型而不是基本“对象”,您将体验到您正在寻找的行为。 c# 中的结构不是引用类型。

希望我没有让你更加困惑?

阅读您的评论后,尝试这样的事情。

List<object> list2 = new List<object>();
for(int i = 0; i < 1000; i++)
{
   List<object>list1 = new List<object>();
   for(int j = 0; j< 1000; j++)
   {
      list1.Add( "something" + j);
   }
   list2.Add(list1);
}

上面将创建一个包含 1000、1000 长度列表的列表。

【讨论】:

  • 感谢您的帮助,但在您的代码中,它应该在另一个对象列表中插入一个对象列表(仅接受类型对象)!!
【解决方案2】:

以下内容:

object = new List<Object>();
allObjects.Add(object);

相当于:

allObjects.Add(new List<Object>());

也相当于:

object = new List<Object>();
allObjects.Add(new List<Object>(object));

在最后一种情况下,您正在创建一个空列表,然后创建另一个空列表,并用第一个列表填充该列表。

编辑:我想通过在此处留​​下这个链接来补充 Jon 所说的话:http://www.yoda.arachsys.com/csharp/parameters.html

这应该可以帮助您理解值类型和引用类型之间的区别,因为我认为这就是您感到困惑的地方。

【讨论】:

  • thaaanksss 4 你的帮助,我会检查链接
【解决方案3】:

在你的评论中你说:

//after filling all the 1000 elements in allObjects list,all the elements of the
//list are 1000 elements with the same value of the last object has been inserted

但是如果你尝试一些简单的事情,比如:

List<List<int>> allObjects = new List<List<int>>(10);
for (int i = 0; i < 10; i++)
{
    var obj = new List<int>();
    obj.Add(i);
    allObjects.Add(obj);
}

然后检查调试器中列表的值,您会看到每个子列表都有一个值为 i 的元素(从 0 到 9)。 所以,在我看来,您的代码在做正确的事情。

当您尝试访问列表中的那些元素并且您只真正访问最后一个元素时,此代码可能会出现问题。

或者您的 Object 类可能是一个只能有一个实例的单例类型类(可能不仅仅是在不知道任何有关 Object 信息的情况下想到的东西)。

【讨论】:

  • thaaanks 4 证明并激励我 :)
【解决方案4】:

我认为您的问题在于“这里有一些填充对象列表的代码”。您放入内部List(您有些混淆地称为“object”)的对象属于引用类型,您可能会将对相同对象的引用放入每个内部列表中。所以即使认为内部的Lists 本身是唯一的实例,它们里面的对象却不是。

【讨论】:

    【解决方案5】:

    感谢大家鼓舞人心的回答和抱歉 4 干扰 实际上我发现问题在于用重复数据填充内部列表本身(使用随机数生成器并且它正在重复数据) 所以这不是我想的引用问题

    【讨论】:

    • 是的,请确保您始终为您的随机数生成器提供种子。我以前就是这样的受害者。 :)
    猜你喜欢
    • 1970-01-01
    • 2011-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多