如何在不使用foreach的情况下将列表中的项目复制到另一个列表?

376

如何在C#中不使用foreach将一个List中的项目转移到另一个List中?


3
如果你需要深度克隆原始列表,你可以在这个相关的问题中找到答案:https://dev59.com/sHVC5IYBdhLWcg3wpi98 - Dirk Vollmar
10个回答

665
你可以尝试这个:
List<Int32> copy = new List<Int32>(original);

或者如果你正在使用 C# 3 和 .NET 3.5,并且使用了 Linq,你可以这样做:

List<Int32> copy = original.ToList();

我看到这个答案仍在得到投票。好吧,这有一个秘密:上面的答案仍在使用foreach。请不要再投票了。


22
如果项目的类型是 MyClass 而不是 Integer,它会复制项目还是只是引用它们? - Pedro Moreira
9
无法处理非基本类型。List<StudentClass> copy = new List<StudentClass>(lstStudentClass);(将lstStudentClass的内容复制到名为copy的新列表中,其中StudentClass是自定义的非基本类型) - garish
4
只要 lstStudentClass 是一个 IEnumerable<StudentClass>,它就可以与所有类型一起使用。如果您遇到其他情况,请提供更多信息。请注意,翻译后的内容意思和原文保持一致,但更加通俗易懂。 - Lasse V. Karlsen
1
什么是(原文)的含义?最后。 - Rahul Chaudhari
3
对于复杂对象,您可以使用original.Select(o => new Complex(o)).ToList()来获取一个新对象列表,而不是复制引用。 - Luke T O'Brien
显示剩余2条评论

207

要将一个已经存在的列表的内容添加到另一个列表中,您可以使用:

targetList.AddRange(sourceList);

如果你只是想创建一个列表的新副本,请参阅顶部答案。


6
他们做的事情不同。我的回答聚焦于“我已经有一个列表,我想要复制其中的内容”。 - Jon Skeet
真的。我的问题可能更适合于一个新问题。不过还是谢谢你的回复。 - mrmillsy
3
如果你想完全替换一个已存在的列表中的内容,首先需要调用 targetList.Clear()。 - Ibraheem
这是正确的答案,因为复制意味着添加,而不是替换。 原帖要求复制项目,而不是整个集合。 - John Stock

44

对于一个元素列表

List<string> lstTest = new List<string>();

lstTest.Add("test1");
lstTest.Add("test2");
lstTest.Add("test3");
lstTest.Add("test4");
lstTest.Add("test5");
lstTest.Add("test6");

如果您想复制所有的元素

List<string> lstNew = new List<string>();
lstNew.AddRange(lstTest);

如果你想复制前三个元素

List<string> lstNew = lstTest.GetRange(0, 3);

1
这是正确的答案。AddRange在文档中没有明确指定它是通过复制还是仅添加对象的引用,但如果您搜索实现,它使用Array.Copy(静态)来复制数据。 - Paul-Sebastian Manole

7

如果需要将单个属性复制到另一个列表中,可以使用以下方法:

targetList.AddRange(sourceList.Select(i => i.NeededProperty));

4

这个方法将创建一个列表的副本,但是您的类型应该是可序列化的。

用途:

List<Student> lstStudent = db.Students.Where(s => s.DOB < DateTime.Now).ToList().CopyList(); 

方法:

public static List<T> CopyList<T>(this List<T> lst)
    {
        List<T> lstCopy = new List<T>();
        foreach (var item in lst)
        {
            using (MemoryStream stream = new MemoryStream())
            {
                BinaryFormatter formatter = new BinaryFormatter();
                formatter.Serialize(stream, item);
                stream.Position = 0;
                lstCopy.Add((T)formatter.Deserialize(stream));
            }
        }
        return lstCopy;
    }

序列化是否会导致显著的性能损失? - Dan Def

4

使用Linq轻松映射不同的列表集,无需使用for循环

var List1= new List<Entities1>();

var List2= new List<Entities2>();

var List2 = List1.Select(p => new Entities2
        {
            EntityCode = p.EntityCode,
            EntityId = p.EntityId,
            EntityName = p.EntityName
        }).ToList();

2

除了前面给出的答案,如果你想要“列表中的对象”的副本,那么可以使用 Select 并制作副本。(而其他答案则是“复制列表”,而这个答案是“副本列表”)。

假设你的项目有一个 Copy 方法:

List<MyObject> newList = oldList.Select(item => item.Copy()).ToList();

或者您可以使用构造函数从先前的对象创建一个新对象:

List<MyObject> newList = oldList.Select(item => new MyObject(item)).ToList();   
Select 的结果是一个 IEnumerable<MyObject>,如果你的目标是向现有列表中添加内容,你可以将其传递给 AddRange

1
public static List<string> GetClone(this List<string> source)
{
    return source.Select(item => (string)item.Clone()).ToList();
}

1
仅提供代码的答案往往被认为是低质量的。您能否添加一个解释,说明您的答案如何解决问题,以及与现有答案的区别。 - Dijkgraaf

-1

好的,这个工作得很好。从上面的建议中可以看出,使用GetRange()方法时,将列表作为参数不起作用...所以从上面的帖子中稍微改进一下:(谢谢大家:)

/*  Where __strBuf is a string list used as a dumping ground for data  */
public List < string > pullStrLst( )
{
    List < string > lst;

    lst = __strBuf.GetRange( 0, __strBuf.Count );     

    __strBuf.Clear( );

    return( lst );
}

3
这甚至不是一个答案。 - Maciej Jureczko
嗯...好吧,上面的一些建议在Vis 17中根本不起作用。我整理了最佳答案...嘿,神奇的是...它可以工作 :) - Jim Stevens

-9
这里有另一种方法,但与其他方法相比稍差。
List<int> i=original.Take(original.count).ToList();

25
为什么要这样做?为什么不直接使用ToList()呢? - nawfal
我认为,如果我想要将一个列表的前10个元素复制到另一个列表中,这是有意义的。 List<int> i=original.Take(10).ToList(); - Chandraprakash

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