C# 两种深拷贝方法效率比较
🏷️ C#
在 CSDN 和 简书 上都看到一种通过 二进制的序列化和反序列化 来实现深拷贝的方式。
感觉这种方式应该比通过反射的方式更快,然而写了点代码测试了之后,结果大出所料。(下面测试中使用的两种实现均来自 这篇博客)
csharp
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.Serialization.Formatters.Binary;
namespace DeepCopyTest
{
class Program
{
static void Main(string[] args)
{
int loop = 10 * 10000;
var staff = new Staff()
{
FirstName = "佳佳",
LastName = "刘",
Site = "liujiajia.me",
};
Stopwatch sw1 = new Stopwatch();
sw1.Start();
for (int i = 0; i < loop; i++)
{
_ = DeepCopyByReflect(staff);
}
sw1.Stop();
Console.WriteLine($"通过 DeepCopyByReflect 方法创建深拷贝耗费 {sw1.ElapsedMilliseconds} ms");
sw1.Reset();
sw1.Start();
for (int i = 0; i < loop; i++)
{
_ = DeepCopyByBin(staff);
}
sw1.Stop();
Console.WriteLine($"通过 DeepCopyByBin 方法创建深拷贝耗费 {sw1.ElapsedMilliseconds} ms");
Console.ReadLine();
}
/// <summary>
/// 深拷贝,通过序列化与反序列化实现
/// </summary>
/// <typeparam name="T">深拷贝的类类型</typeparam>
/// <param name="obj">深拷贝的类对象</param>
/// <returns></returns>
public static T DeepCopyByBin<T>(T obj)
{
object retval;
using (MemoryStream ms = new MemoryStream())
{
BinaryFormatter bf = new BinaryFormatter();
//序列化成流
bf.Serialize(ms, obj);
ms.Seek(0, SeekOrigin.Begin);
//反序列化成对象
retval = bf.Deserialize(ms);
ms.Close();
}
return (T)retval;
}
/// <summary>
/// 深拷贝,通过反射实现
/// </summary>
/// <typeparam name="T">深拷贝的类类型</typeparam>
/// <param name="obj">深拷贝的类对象</param>
/// <returns></returns>
public static T DeepCopyByReflect<T>(T obj)
{
//如果是字符串或值类型则直接返回
if (obj is string || obj.GetType().IsValueType) return obj;
object retval = Activator.CreateInstance(obj.GetType());
FieldInfo[] fields = obj.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
foreach (FieldInfo field in fields)
{
try { field.SetValue(retval, DeepCopyByReflect(field.GetValue(obj))); }
catch { }
}
return (T)retval;
}
}
[Serializable]
class Staff
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Site { get; set; }
}
}
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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
上述代码输出如下:
txt
通过 DeepCopyByReflect 方法创建深拷贝耗费 87 ms
通过 DeepCopyByBin 方法创建深拷贝耗费 955 ms
1
2
2
可以发现通过 反射 的实现比通过 二进制序列化反序列化 的实现效率高 10 倍以上。
2020-05-12 追记
最近发现在有数组/列表属性时,上文的 DeepCopyByReflect 方法会报异常。
另外新增了一种通过 JSON 的实现。
详情见 => C# 深拷贝方法效率比较(2)