dotnet中的克隆(Clone)

.net中的数据类型分为值类型和引用类型。

值类型包括:bool 、byte 、char 、decimal 、double 、enum 、float 、int 、long 、sbyte 、short 、struct 、uint 、ulong 、ushort

引用类型包括:class 、interface 、delegate 、object 、string

在进行数据赋值时,值类型会复制一份数据内容,赋值给新的变量,因此,当新值修改时,原值将不会发生改变;而引用类型会将数据的地址赋值给新变量,所以当新变量修改时,会同时修改原数据内容,这种赋值为“浅克隆”,或“浅拷贝”。

当需要将引用类型的数据复制为一个独立的新数据时,需要将原数据重新复制一份(在堆中),这种操作称为”深克隆“,或“深拷贝”。dotnet中常见的有两种实现深克隆的方式:手动克隆和使用二进制序列化克隆。

以下是示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
[Serializable]
public class MyObject
{
public string Property1 { get; set; }

/// <summary>
/// 浅克隆(浅拷贝)
/// </summary>
/// <returns></returns>
public MyObject Clone()
{
return (MyObject)this.MemberwiseClone();
}

/// <summary>
/// 深克隆(深拷贝),需要手动为各个属性/字段赋值
/// </summary>
/// <returns></returns>
public MyObject DeepClone1()
{
var newObj = new MyObject
{
Property1 = this.Property1
};

return newObj;
}

/// <summary>
/// 深克隆(深拷贝),使用二进制序列化的方式。由于需要进行序列化操作,所以必须用[Serializable]特性修饰类
/// </summary>
/// <returns></returns>
public MyObject DeepClone2()
{
IFormatter formatter = new BinaryFormatter();
using var stream = new MemoryStream();
formatter.Serialize(stream, this);
stream.Seek(0, SeekOrigin.Begin);
return (MyObject)formatter.Deserialize(stream);
}
}

BinaryFormatter在微软官方文档中已被标记为过时,具体见BinaryFormatter安全指南

分享到