【CSharp】深拷贝

浅拷贝和深拷贝的区别

  • 浅拷贝只是拷贝了原对象的引用,而不是对象本身。因此,浅拷贝后的对象与原对象共享内存空间,即修改其中一个对象的值会影响到另一个对象的值
  • 深拷贝则是完全拷贝了原对象及其引用的对象,因此,深拷贝后的对象与原对象不共享内存空间,即修改其中一个对象的值不会影响到另一个对象的值

在C#中深拷贝的用法

反射

输入的对象可以和输出的对象不一样。如果输出的对象拥有与输入的对象相同的属性,则会把该属性的值赋给输出对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private static TOut TransReflection<TIn, TOut>(TIn tIn)
{
// 创建一个新的 TOut 实例
TOut tOut = Activator.CreateInstance<TOut>();
// 获取到 tIn 的类型
var tInType = tIn.GetType();
// 遍历 TOut 的属性
foreach (var itemOut in tOut.GetType().GetProperties())
{
// 获取到 tIn 的属性
var itemIn = tInType.GetProperty(itemOut.Name);

if (itemIn != null)
{
// 将 tIn 的属性赋给 tOut 的对应属性
itemOut.SetValue(tOut, itemIn.GetValue(tIn));
}
}
return tOut;
}

第二种反射反射深拷贝函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public static T DeepCopy<T>(T obj)
{
if (obj == null)
{
return obj;
}
var type = obj.GetType();
if (obj is string || type.IsValueType)
{
return obj;
}

var result = Activator.CreateInstance(type);
var fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance);
foreach (var field in fields)
{
field.SetValue(result, field.GetValue(obj));
}
return (T)result;
}

完整代码如下:

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
using System;

namespace AsyncTest
{
class Program
{
static void Main(string[] args)
{
Player A = new Player("A", 10);
//Player B = A; // 浅拷贝
Player B = TransReflection<Player, Player>(A); // 深拷贝
B.Age = 20;
Console.WriteLine($"{A.Name} {A.Age}");
Console.WriteLine($"{B.Name} {B.Age}");
Console.ReadKey();
}
private static TOut TransReflection<TIn, TOut>(TIn tIn)
{
// 创建一个新的 TOut 实例
TOut tOut = Activator.CreateInstance<TOut>();
// 获取到 tIn 的类型
var tInType = tIn.GetType();
// 遍历 TOut 的属性
foreach (var itemOut in tOut.GetType().GetProperties())
{
// 获取到 tIn 的属性
var itemIn = tInType.GetProperty(itemOut.Name);

if (itemIn != null)
{
// 将 tIn 的属性赋给 tOut 的对应属性
itemOut.SetValue(tOut, itemIn.GetValue(tIn));
}
}
return tOut;
}
}
public class Player
{
public string Name { get; set; }
public int Age { get; set; }
public Player() { }
public Player(string name, int age)
{
this.Name = name;
this.Age = age;
}
}
}