复制List< T>.添加(T项)项
本文关键字:添加 List 复制 | 更新日期: 2023-09-27 18:04: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);
}
}
}
}
您已将同一项aFoo
添加了5次。当您修改引用类型对象的内容时,您不会创建新的副本,而是修改相同的对象。
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在列表中时,您仍在修改它。
您已经向列表中添加了对同一对象的引用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();
输出:<>之前使用aFooList011222333344444使用foo01234 变量'aFoo'基本上是指向内存中某个位置的指针。如果不"更新"另一个实例(malloc),您将修改内存中的相同位置并添加相同的指针5次。
对于c#程序员来说,"new"关键字就像malloc在C中所做的那样完成函数。它将获得一个新的内存位置,并使aFoo指向该位置,而不是旧的位置。
从MSDN:The new operator is used to create objects and invoke constructors
MSDN