The*_*lar 59 c# clone list deep-copy
在下面的代码中,
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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
我使用一个Book
对象类型来创建一个List<T>
,我用几个项目填充它,给它们一个唯一的标题(从'one'到'five').
然后我创造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
该类可能更复杂,具有更多属性.我试着保持简单.
Mar*_*ers 96
您需要创建新Book
对象,然后将它们放入新对象中List
:
List<Book> books_2 = books_1.Select(book => new Book(book.title)).ToList();
Run Code Online (Sandbox Code Playgroud)
更新:稍微简单... List<T>
有一个调用的方法ConvertAll
返回一个新列表:
List<Book> books_2 = books_1.ConvertAll(book => new Book(book.title));
Run Code Online (Sandbox Code Playgroud)
Tre*_*ley 31
创建一个ICloneable<T>
在Book
类中实现的通用接口,以便类知道如何创建自身的副本.
public interface ICloneable<T>
{
T Clone();
}
public class Book : ICloneable<Book>
{
public Book Clone()
{
return new Book { /* set properties */ };
}
}
Run Code Online (Sandbox Code Playgroud)
然后,您可以使用ConvertAll
Mark提到的linq或方法.
List<Book> books_2 = books_1.Select(book => book.Clone()).ToList();
Run Code Online (Sandbox Code Playgroud)
要么
List<Book> books_2 = books_1.ConvertAll(book => book.Clone());
Run Code Online (Sandbox Code Playgroud)
svi*_*ick 17
我很失望微软没有像Ruby那样提供一个简洁,快速,简单的解决方案
clone()
.
除非不创建深层副本,否则会创建浅层副本.
通过深度复制,您必须始终小心,您想要复制什么.可能的问题的一些例子是:
Book
有一个Author
并且Author
有一个他Book
的列表.Stream
写入文件的open .Window
.现在,基本上有两种克隆方法:
Clone()
在每个需要克隆的类中实现一个方法.(也有ICloneable
接口,但你应该不会使用;使用自定义ICloneable<T>
.接口特雷弗建议是好的)如果你知道所有你需要的是创建该类的每个字段的一个浅拷贝,你可以使用MemberwiseClone()
来实现它.作为替代方案,您可以创建一个"复制构造函数":public Book(Book original)
.MemoryStream
然后反序列化它们.这要求您将每个类标记为[Serializable]
,并且还可以配置应该序列化的确切(以及如何).但这更像是一种"快速而肮脏"的解决方案,并且很可能也会降低性能.Hos*_*imi 12
C# 9记录和with 表达式可以使它变得更容易一些,特别是当您的类型有很多属性时。
你可以使用类似的东西:
var books2 = books1.Select(b => b with { }).ToList();
Run Code Online (Sandbox Code Playgroud)
我这样做了一个例子:
record Book
{
public string Name { get; set; }
}
static void Main()
{
List<Book> books1 = new List<Book>()
{
new Book { Name = "Book1.1" },
new Book { Name = "Book1.2" },
new Book { Name = "Book1.3" }
};
var books2 = books1.Select(b => b with { }).ToList();
books2[0].Name = "Changed";
books2[1].Name = "Changed";
Console.WriteLine("Books1 contains:");
foreach (var item in books1)
{
Console.WriteLine(item);
}
Console.WriteLine("Books2 contains:");
foreach (var item in books2)
{
Console.WriteLine(item);
}
}
Run Code Online (Sandbox Code Playgroud)
输出为:(对 Books2 中的对象进行的更改不会影响 Books1 中的原始对象)
书籍 1 包含:
书 { 名称 = Book1.1 }
书 { 名称 = Book1.2 }
书 { 名称 = Book1.3 }
Books2 包含:
书 { 名称 = 已更改 }
书 { 名称 = 已更改 }
书 { 名称 = Book1.3 }
小智 10
List<Book> books_2 = new List<Book>(books_2.ToArray());
Run Code Online (Sandbox Code Playgroud)
这应该完全符合你的要求.在这里展示.
小智 9
你可以使用这个:
var newList= JsonConvert.DeserializeObject<List<Book>>(list.toJson());
Run Code Online (Sandbox Code Playgroud)
好,
如果将所有涉及的类标记为可序列化,则可以:
public static List<T> CloneList<T>(List<T> oldList)
{
BinaryFormatter formatter = new BinaryFormatter();
MemoryStream stream = new MemoryStream();
formatter.Serialize(stream, oldList);
stream.Position = 0;
return (List<T>)formatter.Deserialize(stream);
}
Run Code Online (Sandbox Code Playgroud)
资源:
归档时间: |
|
查看次数: |
121016 次 |
最近记录: |