【问题标题】:deep copy without using serialize/deserialize不使用序列化/反序列化的深拷贝
【发布时间】:2022-01-12 15:56:51
【问题描述】:

在不进行序列化/反序列化的情况下将类对象复制到多深?

例如

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: 化学
新书页数:60

oldBook.Chapter: 物理
oldBook.Page: 40

【问题讨论】:

标签: c# deep-copy


【解决方案1】:

当对象具有足够的属性以至于编写自定义代码会很耗时时,序列化和反序列化很受欢迎,但您可以编写:

public static class BookExtensions
{
    public static Book Clone(this Book source)
    {
        return new Book {Chapter = source.Chapter, Page = source.Page};
    }
}

或将其设为Book 的方法。是这样做还是创建扩展(上图)是一个偏好问题。如果方法在 Book 中,那么您更有可能记得在类更改时更新方法。

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 方法返回object,你必须强制转换它。)

另一种方法是使用structrecord。您可能会进行克隆以便拥有与另一个实例相同的实例,但您可以在不更改第一个实例的情况下修改其属性。

如果您将 Book 类更改为 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}; 之类的语句会创建一本新书并仅更新指定的属性。无需克隆。

【讨论】:

  • 但这不是深度克隆。
  • 第一部分是深度克隆。第二部分是关于为什么需要深度克隆,并质疑我们是否可以消除对它的需求。
猜你喜欢
  • 2014-10-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-17
  • 1970-01-01
  • 2017-06-07
  • 2022-12-09
相关资源
最近更新 更多