重复列表<t>。添加(T项)项</t>

时间:2013-03-19 21:30:58

标签: c# list

为什么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);
            }
        }
    }
}

4 个答案:

答案 0 :(得分:4)

您添加了相同的项目aFoo,共5次。修改引用类型对象的内容时,如果不创建新副本,则修改同一对象。

答案 1 :(得分: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。

答案 2 :(得分:0)

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

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

来自MSDN:

The new operator is used to create objects and invoke constructors

MSDN

答案 3 :(得分:0)

您已将同一对象的引用添加到列表中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();

输出:

Using aFooList
0
11
222
3333
44444

Using foos
01234