C#如何正确的做深拷贝
估计很多人在网上看到各种各样的DeepClone实现, 例如:
1. 通过BinaryFormatter进行二进制序列化
这玩意儿序列化出来的东西还带namespace类型, 尺寸非常大, 调试一下就知道极其不靠谱
有些人又开始动歪脑筋了, 说我搞一个JSON序列化, 或者BSON序列化可不可以
2. JSON/BSON序列化
本质问题还是一样的, Object => byte[] => Object, 中间产生的垃圾对象太多, 尤其是Stream那些
所以, 我们需要思考DeepClone的本质是啥!
如果现在有一个类A, 你自己手写一个Clone函数, 那么是不是可以做到效率最高? 答案是显然的, 我知道有什么成员, new一个对象分别赋值就行了.
但是如果这个类A成天改, 维护的成本就比较高昂, 万一哪天忘了改, 就会出现一些奇妙的BUG.
所以, 类A的Clone函数, 是一个重复性的工作.
所有重复性的工作, 都可以通过代码生成来搞.
那么会有很多代码生成的答案:
3. 写一个DSL编译器
不要嘲笑这种方式, protobuf在C++的实现里面, 就有一个原型工厂, 做的是类似的事情. C++里面没有反射只能通过这种方式, 只要把这些脏活累活交给编译器就可以了.
唯一不同的是, 这是编译前代码生成.
4. 通过Emit生成代码
我们都知道.NET平台有比较强的动态性, 可以动态的load/unload assembly. 甚至还可以动态的构造assembly和class和function.
所以, 我们可以对类A生成一个Clone函数, 通过反射获取到其成员, 然后动态生成其Clone函数, 就相当于手写的代码, 效率可以做到最高.
然后可以把生成的函数保存起来. JIT也能对其进行优化.
具体实现可以参考: DeepCloner
去他的GITHUB上面瞄一眼就知道是最佳姿势.
5. 通过ExpressionTree生成代码
表达式树也可以生成代码, 具体可以 参考一下
https://www.codeproject.com/articles/1111658/fast-deep-copy-by-expression-trees-c-sharp
https://stackoverflow.com/questions/23229882/deep-clone-with-expression-new-and-expression-trees
开头那些序列化, 一看就不靠谱, 不知道为啥流传了这么多年
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律