【问题标题】:Duplicate List<T>.Add(T item) Items重复列表<T>.Add(T item) 项
【发布时间】:2013-03-08 19:06:40
【问题描述】:

为什么aFooList 包含最后一项的五个副本,而不是我插入的五个项?

预期输出:01234

实际输出:44444

using System;
using System.Collections.Generic;

namespace myTestConsole {
    public class foo {
        public int bar;
    }

    class Program {
        static void Main(string[] args) {
            foo aFoo = new foo(); // Make a foo
            List<foo> aFooList = new List<foo>(); // Make a foo list

            for (int i = 0; i<5; i++) { 
                aFoo.bar = i;
                aFooList.Add(aFoo);
            }

            for (int i = 0; i<5; i++) {
                Console.Write(aFooList[i].bar);
            }
        }
    }
}

【问题讨论】:

  • 您只创建了一个 foo 对象,并将其添加到列表中 5 次

标签: c# list


【解决方案1】:

您已经添加了 5 次相同的项目 aFoo。当您修改引用类型对象的内容时,您不会创建新副本,而是修改了同一个对象。

【讨论】:

    【解决方案2】:
    List<foo> aFooList = new List<foo>(); // Make a foo list
    
    for (int i = 0; i<5; i++) { 
        foo aFoo = new foo(); // Make a foo
        aFoo.bar = i;
        aFooList.Add(aFoo);
    }
    

    您仍在修改列表中的 aFoo。

    【讨论】:

      【解决方案3】:

      您已向列表中添加了 5 次对同一对象的引用,每次都修改 bar 的值。在aFooList.Add(aFoo); 之后添加这一行,以查看每次在列表中添加foo 时的效果。

      Console.WriteLine(string.Join("", foos.Select(f => f.bar)));
      

      对于它的价值,它是一个带有 Linq 的单行(间隔很好以提高可读性)。

      var foos = Enumerable.Range(0, 5)
                           .Select(n => new foo {bar = n})
                           .ToList();
      

      完整示例:

      foo aFoo = new foo(); // Make a foo
      List<foo> aFooList = new List<foo>(); // Make a foo list
      Console.WriteLine("\nUsing aFooList");
      for (int i = 0; i < 5; i++)
      {
          aFoo.bar = i;
          aFooList.Add(aFoo);
          Console.WriteLine(string.Join("", aFooList.Select(f => f.bar)));
      }
      
      var foos = Enumerable.Range(0, 5).Select(n => new foo { bar = n }).ToList();
      Console.WriteLine("\nUsing foos");
      Console.WriteLine(string.Join("", foos.Select(f => f.bar)));
      
      Console.ReadLine();
      

      输出:

      使用 FooList 0 11 222 3333 44444 使用 foos 01234

      【讨论】:

        【解决方案4】:

        您的变量“aFoo”基本上是指向内存中某个位置的指针。如果不“更新”另一个实例 (malloc),您将修改内存中的相同位置并添加相同的指针 5 次。

        就程序员而言,“new”关键字在 C# 中完成了函数,就像 malloc 在 C 中所做的那样。它将获得一个新的内存位置并使 aFoo 指向该位置,而不是旧的。

        来自 MSDN:

        The new operator is used to create objects and invoke constructors
        

        MSDN

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-08-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-01-29
          • 1970-01-01
          相关资源
          最近更新 更多