List.Add似乎在复制条目,这是怎么回事?

3

我有一个类似这样的类:

public class myClass
{
  public List<myOtherClass> anewlist = new List<myOtherClass>;

  public void addToList(myOtherClass tmp)
  {
    anewList.Add(tmp);
  }

}

所以我调用“addToList”一百次,每次都向列表中添加一个独特的项目。在运行“addToList”方法之前,我测试了我的项目以显示它们是唯一的。我甚至加入了一行代码来测试“tmp”,确保它是我期望的。

然而,当我这样做时(假设myClass对象被称为tmpClass):

int i = tmpClass.anewList.Count();
for (int j = 0; j<i; j++)
{
   //write out each member of the list based on index j...
}

我得到了完全相同的项目,并且它是最后一个写入我的列表中的项目。就好像当我添加时,我正在用我添加的最后一个项目覆盖整个列表。
有帮助吗?这毫无意义。 我还尝试过List.Insert,其中我总是在末尾或索引0处插入。仍然不行。是的,我双重检查了我的索引是否正确,并且当我进行测试时,我正在遍历每个元素。
:)
更新: 好吧,我尝试过这个,但仍然有同样的问题:
foreach(myOtherClass tmpC in tmpClass.anewList)
{    
    Console.WriteLine(tmpC.theStringInMyClass.ToString());
}

对于这100个项目中的每一个,我都得到了相同的字符串输出……我确定我做了些非常愚蠢的事情,但我还不知道是什么。我仍然百分之百地确信一开始传入的字符串是正确的。
-Adeena
好的,我尝试过这个方法,但仍然存在同样的问题。
foreach(myOtherClass tmpC in tmpClass.anewList)
{
    Console.WriteLine(tmpC.theStringInMyClass.ToString());
}

对于这100个项目中的每一个,我仍然得到了相同的字符串输出…… 我确信我正在做一些非常愚蠢的事情,但我还不知道是什么。 我仍然100%确定正确的字符串一开始就被传递进去了。

-Adeena


你能否贴出更多的代码 - 问题可能在于你添加或读取列表的方式... - flesh
您还没有发布足够的代码! - flesh
6个回答

14

考虑到你的 addToList 方法的签名:

public void addToList(myOtherClass tmp)
  {
    anewList.Add(tmp);
  }

在这个方法的消费者中,你有没有可能实际上并没有创建一个新的实例?

你说你要调用addToList 100次。假设这是在一个循环中完成的,在每次循环迭代中,你都需要创建一个“myOtherClass”的新实例,否则,你只会更新内存中的同一个对象。

例如,如果你按照下面的方式操作,你将获得100份相同对象的副本:

myOtherClass item = new myOtherClass();

for(int i=0; i < 100; i++)
{
  item.Property = i;
  addToList(item);
}

然而,如果您的循环如下所示,则可以正常工作:

myOtherClass item = null;
for(int i=0; i < 100; i++)
{
  item = new myOtherClass();
  item.Property = i;
  addToList(item);
}
希望这有所帮助!

正是我的猜测:他可能会将同一个引用添加到实例中一百次。 - VVS
我是C#的新手,我刚意识到他们的列表有一个“特殊”的引用,指向每个列表项,这在大多数其他语言中不适用。谢谢。 - Dan

2
在这种情况下,查看您如何验证每个项目以确保项目是唯一的可能会有所帮助。如果您可以展示类的ToString()方法,它可能会有所帮助:您可能基于实际上在每个对象之间相同的某些内容。这可能有助于确定您是否真的每次都得到相同的对象,或者考虑的部分确实不是唯一的。
此外,尽可能使用foreach循环而不是按索引访问。
最后,列表中的项目并非普遍唯一,而是指向其他地方存在的对象的引用。如果您试图检查检索的项目相对于外部对象是唯一的,那么您将失败。
还有一件事,我想说的是:您可能希望让对anewList的访问权限为private而不是public。

1
尝试使用foreach而不是索引来遍历列表。我怀疑问题出在你省略的代码中,而不是列表本身。
foreach (MyOtherClass item in tmpClass.anewList)
{
     Console.WriteLine( item );  // or whatever you use to write it
}

编辑

您是否在调试器中检查了列表结构,以确保实际添加了您的唯一项?此外,您可能希望使用.Count(属性)而不是.Count()(扩展方法)。扩展方法可能会遍历列表以计算方法,而属性只是查找保存计数的私有变量的值。

@James可能有所发现。如果您只是更改已插入的项目的属性并重新插入它,而不是每次创建新对象,则会导致您看到的行为。


1

根据我在这里阅读的内容,我认为你的问题可能出在添加列表项上 - 你确定你没有一遍又一遍地添加相同的引用吗?这可能是你的列表中有100个“最后一项”的原因。


是的 - 就是这样。 :) -A - adeena

0

另外请注意,当您使用精确形式时:

 for (int j = 0; j < tmpClass.anewList.Count(); j++)

C#编译器对循环执行特殊优化。如果您违背了语法(例如,将Count属性从循环中提取到单独的变量中,就像在您的示例中所做的那样),则编译器会跳过该优化。 这不会影响显示内容,但它会花费更长时间。

0

明白了!谢谢James -

这就是我做错的蠢事:

我之前写成:

myClass tmpClass = new myClass();
myOtherClass anewitem = new myOtherClass();
string tst = "";

for (int i = 0; i < 100; i++) 
{
    tst += "blah";
    anewitem.theStirngInMyClass = tst;
    tmpClass.AddToList(anewitem);
}

当我将它改为这样时:

myClass tmpClass = new myClass();
string tst = "";

for (int i = 0; i < 100; i++) 
{
    myOtherClass anewitem = new myOtherClass()
    tst += "blah";
    anewitem.theStringInMyClass = tst;
    tmpClass.AddToList(tst);
}

一切都很好。我明白了。:)

感谢大家的帮助!

- Adeena


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接