为了账号安全,请及时绑定邮箱和手机立即绑定

如何创建List <T>的新深层副本(克隆)?

/ 猿问

如何创建List <T>的新深层副本(克隆)?

C#
慕仰1329654 2019-11-15 10:44:02

在下面的代码中,


using System;

using System.Collections.Generic;

using System.Drawing;

using System.Windows.Forms;


namespace clone_test_01

{


    public partial class MainForm : Form

    {


        public class Book

        {

            public string title = "";


            public Book(string title)

            {

                this.title = title;

            }

        }



        public MainForm()

        {

            InitializeComponent();


            List<Book> books_1 = new List<Book>();

            books_1.Add(  new Book("One")  );

            books_1.Add(  new Book("Two")  );

            books_1.Add(  new Book("Three")  );

            books_1.Add(  new Book("Four")  );


            List<Book> books_2 = new List<Book>(books_1);


            books_2[0].title = "Five";

            books_2[1].title = "Six";


            textBox1.Text = books_1[0].title;

            textBox2.Text = books_1[1].title;

        }

    }


}

我使用一种Book对象类型创建一个,List<T>然后在其中填充一些项目,使它们具有唯一的标题(从“一个”到“五个”)。


然后我创建List<Book> books_2 = new List<Book>(books_1)。


从这一点来看,我知道它是列表对象的克隆,但书对象book_2仍然来自中的书对象的引用books_1。它是通过使上的两个第一要素的变化证明books_2,然后检查这些相同的元素book_1在TextBox。


books_1[0].title and books_2[1].title确实已更改为的新值books_2[0].title and books_2[1].title。


现在的问题


我们如何创建的新硬拷贝List<T>?这个想法是,books_1并且books_2变得彼此完全独立。


令我感到失望的是,微软没有提供像Ruby那样使用该clone()方法的简洁,快速,简便的解决方案。


助手们真的很棒的是使用我的代码并使用可行的解决方案对其进行更改,以便可以对其进行编译和工作。我认为这将真正帮助尝试了解该问题提供的解决方案的新手。


编辑:请注意,Book该类可能更复杂并且具有更多属性。我试图使事情简单。


查看完整描述

3 回答

?
www说

您需要创建新Book对象,然后将其放在新对象中List:


List<Book> books_2 = books_1.Select(book => new Book(book.title)).ToList();

更新:稍微简单一点... List<T>有一种方法ConvertAll可以返回新列表:


List<Book> books_2 = books_1.ConvertAll(book => new Book(book.title));


查看完整回答
反对 回复 2019-11-15
?
当年话下

创建一个ICloneable<T>在Book类中实现的通用接口,以便该类知道如何创建其自身的副本。


public interface ICloneable<T>

{

    T Clone();

}


public class Book : ICloneable<Book>

{

    public Book Clone()

    {

        return new Book { /* set properties */ };

    }

}

然后,您可以使用linq或ConvertAllMark提到的方法。


List<Book> books_2 = books_1.Select(book => book.Clone()).ToList();

要么


List<Book> books_2 = books_1.ConvertAll(book => book.Clone());


查看完整回答
反对 回复 2019-11-15
?
大话西游666

令我感到失望的是,微软没有提供像Ruby那样使用该clone()方法的简洁,快速,简便的解决方案。


除了不创建深层副本外,它还会创建浅层副本。


使用深层复制时,您必须始终小心,要复制什么。可能的问题的一些示例是:


在对象图中循环。例如,Book具有Author和Author的列表Book。

引用某些外部对象。例如,一个对象可能包含Stream写入文件的open 。

活动。如果一个对象包含一个事件,几乎任何人都可以订阅它。如果订户是GUI之类的话,这可能会特别成问题Window。

现在,基本上有两种方法可以克隆某些东西:


Clone()在您需要克隆的每个类中实现一个方法。(也有ICloneable接口,但你应该不会使用;使用自定义的ICloneable<T>界面,特雷弗建议是好的。)如果你知道所有你需要的是创建该类的每个字段的一个浅拷贝,你可以使用MemberwiseClone()来实现它。或者,您可以创建一个“副本构造函数”:public Book(Book original)。

使用序列化将您的对象序列化为MemoryStream,然后反序列化它们。这要求您将每个类标记为[Serializable],并且还可以配置将什么序列化(以及如何序列化)。但是,这更像是一种“快速而肮脏的”解决方案,并且很有可能性能也会降低。


查看完整回答
反对 回复 2019-11-15

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信