不使用 serialize/deserialize 的深层复制
deep copy without using serialize/deserialize
如何在不执行 serialize/deserialize 的情况下深度复制 class 对象?
例如
public class Book
{
public string Chapter { get; set;}
public int Page { get; set;}
}
public void Main ()
{
Book newBook = new Book();
newBook.Chapter = "Physical";
newBook.Page = 40;
Book oldBook = newBook;
newBook.Chapter = "Chemical";
newBook.Page = 60;
}
------------------------------
output
newBook.Chapter: Chemical
newBook.Page: 60
oldBook.Chapter: Chemical
oldBook.Page: 60
但我想要这个
newBook.Chapter:化学品
newBook.Page: 60
oldBook.Chapter:物理
oldBook.Page: 40
当对象具有足够多的属性以至于编写自定义代码会很耗时时,序列化和反序列化很流行,但您可以只写:
public static class BookExtensions
{
public static Book Clone(this Book source)
{
return new Book {Chapter = source.Chapter, Page = source.Page};
}
}
或者使之成为Book
的方法。是执行此操作还是创建扩展(如上)是一个偏好问题。如果该方法在 Book
中,那么您更有可能记得在 class 发生变化时更新该方法。
public class Book
{
public string Chapter { get; set; }
public int Page { get; set; }
public Book Clone()
{
return new Book {Chapter = Chapter, Page = Page};
}
}
(有一个ICloneable
接口你可以实现,但它不流行。Clone
方法returns object
你必须转换它。)
另一种方法是使用 struct
或 record
。您可能正在克隆,以便您可以拥有与另一个实例相同的实例,但您可以修改其属性而不更改第一个实例。
如果您将 Book
class 更改为 struct
,则此测试通过:
var book = new Book {Chapter = "x", Page = 1};
var book2 = book;
book2.Page = 2;
Assert.AreEqual(1, book.Page);
不需要克隆任何东西。
或者您可以创建 record
:
public record class Book(string chapter, int page)
{ }
并且此测试通过:
var book = new Book("x", 1);
var book2 = book with {page = 2};
Assert.AreEqual(1, book.page);
每个 Book
都是不可变的。您可以将它传递给各种方法,每当 属性 需要“更改”时,像 var book2 = book with {page = 2};
这样的语句会创建一本新书,并且只更新指定的 属性。无需克隆。
如何在不执行 serialize/deserialize 的情况下深度复制 class 对象?
例如
public class Book
{
public string Chapter { get; set;}
public int Page { get; set;}
}
public void Main ()
{
Book newBook = new Book();
newBook.Chapter = "Physical";
newBook.Page = 40;
Book oldBook = newBook;
newBook.Chapter = "Chemical";
newBook.Page = 60;
}
------------------------------
output
newBook.Chapter: Chemical
newBook.Page: 60
oldBook.Chapter: Chemical
oldBook.Page: 60
但我想要这个
newBook.Chapter:化学品
newBook.Page: 60
oldBook.Chapter:物理
oldBook.Page: 40
当对象具有足够多的属性以至于编写自定义代码会很耗时时,序列化和反序列化很流行,但您可以只写:
public static class BookExtensions
{
public static Book Clone(this Book source)
{
return new Book {Chapter = source.Chapter, Page = source.Page};
}
}
或者使之成为Book
的方法。是执行此操作还是创建扩展(如上)是一个偏好问题。如果该方法在 Book
中,那么您更有可能记得在 class 发生变化时更新该方法。
public class Book
{
public string Chapter { get; set; }
public int Page { get; set; }
public Book Clone()
{
return new Book {Chapter = Chapter, Page = Page};
}
}
(有一个ICloneable
接口你可以实现,但它不流行。Clone
方法returns object
你必须转换它。)
另一种方法是使用 struct
或 record
。您可能正在克隆,以便您可以拥有与另一个实例相同的实例,但您可以修改其属性而不更改第一个实例。
如果您将 Book
class 更改为 struct
,则此测试通过:
var book = new Book {Chapter = "x", Page = 1};
var book2 = book;
book2.Page = 2;
Assert.AreEqual(1, book.Page);
不需要克隆任何东西。
或者您可以创建 record
:
public record class Book(string chapter, int page)
{ }
并且此测试通过:
var book = new Book("x", 1);
var book2 = book with {page = 2};
Assert.AreEqual(1, book.page);
每个 Book
都是不可变的。您可以将它传递给各种方法,每当 属性 需要“更改”时,像 var book2 = book with {page = 2};
这样的语句会创建一本新书,并且只更新指定的 属性。无需克隆。