10 月 23 - 25 日,QCon 上海站即将召开,现在购票,享9折优惠 了解详情
写点什么

简化 C#的不可变对象图

  • 2013-05-15
  • 本文字数:1070 字

    阅读完需:约 4 分钟

在 C#中创建一个简单的不可变类很容易,开发者只需要创建一个构造函数且不创建公共 setter。但这往往还不够。最终开发者或许会想要创建深层图,考虑到效率原因,应该通过建造者(builder)创建它。或者也许开发者想要创建一些方法,返回包含已变更字段的该对象的复本(如 DateTime 的 AddMinutes 方法),以此来实现非破坏性更新。构建全部这些建造者和方法非常冗长乏味,因此也容易出错。

Andrew L Arnott 提出了一个解决方案,它依靠基于 T4 的代码生成器。T4 代表“文本模版转换工具包”,Text Template Transformation Toolkit。它处于 Visual Studio 代码生成功能的核心位置,诸如实体框架等库都依赖它。Andrew 的 T4 脚本接收一个可变类并创建一个不可变的版本。

该工具包做出了一个略有争议的决定,即不生成公共构造器。相反,他期望开发者使用静态的 Create 方法,或是从 Default 实例开始然后修改它。这通过使用 WithXxx 方法实现,每个属性都有一个对应的方法。

不过,我们可以做更多的改进。对拥有许多属性的类,如果我们需要一次改变若干属性,那么在每个属性变更时都分配一个新对象作为中间步骤,将是一种浪费并且会增加 GC 的压力。因此我们还添加了一个 With 方法,为每个出现在类中的属性接收可选参数,从而支持属性的批量变更。最后,对于需要对对象进行多处变更,却又希望通过多个步骤实现(或者只是倾向于使用属性 setter 而不是调用 With- 方法)的场景,我们可以创建一个 Builder 类,它在构建过程中使用可变的类 ,并且将在完成后返回一个不可变复本。这一模式与.Net Framework 中的 String 和 StringBuilder 非常类似,也与之前提到过的最新不可变集合相似。

当然,如果开发者不喜欢这些决定,也可以很容易地修改 T4 模版。Andrew 故意将模版分解成更小的文件,从而让修改变得更容易。开发者还可以添加自己的扩展而无需对基础模版进行重大改变。

与所有良好编写的代码生成器相似,这里也大量使用了分部方法。分部方法允许开发者向代码生成器生成的方法中添加额外的逻辑,而不必修改生成的文件。例如,开发者可以实现一个类来为不可变对象设定部分默认值。未实现的分部方法将被编译器自动剥离出来,因此不会导致运行时开销。

开发者如果希望进一步了解 Arron 的实验,可以在他的博客中阅读关于不可变对象图的文章。

查看英文原文 Making Immutable Object Graphs Easier in C#


感谢姚琪琳对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ )或者腾讯微博( @InfoQ )关注我们,并与我们的编辑和其他读者朋友交流。

2013-05-15 09:272133
用户头像

发布了 256 篇内容, 共 84.2 次阅读, 收获喜欢 10 次。

关注

评论

发布
暂无评论
发现更多内容

阿里是如何使用分布式架构的?阿里内部学习手册分享

Java你猿哥

分布式 ssm 分布式架构 分布式实战

太全了!马士兵内部共享—1658页《Java面试突击核心讲》

Java java面试 Java八股文 Java面试题 Java面试八股文

我有一篇Java Stream使用手册,学了就是你的了!

狂刷《Java权威面试指南(阿里版)》,冲击“金三银四”有望了

Java java面试 Java八股文 Java面试题 Java面试八股文

人工智能打造充满创造力的新世界,华为云开发者日无锡站成功举办

极客天地

软件工程中建模的底层逻辑

阿里技术

软件工程 建模

源码中常见的 where 1=1 是一种高级优化技巧?

Java你猿哥

Java 源码 ssm

人工智能打造充满创造力的新世界,华为云开发者日无锡站成功举办

华为云开发者联盟

人工智能 华为云 元宇宙 华为云开发者联盟 企业号 3 月 PK 榜

JVM级别的本地缓存框架Guava Cache:探寻实现细节与核心机制

Java你猿哥

Java JVM ssm Guava Cache

软件测试/测试开发丨app自动化测试之Appium WebView 技术原理

测试人

软件测试 自动化测试 测试开发 appium

喜讯:祝贺行云绽放荣获深圳市专精特新企业称号

行云管家

云计算 深圳 专精特新

JDK20正式发布了GA版本,短期维护支持,以及JDK21预览

小小怪下士

Java 程序员 jdk 后端

详解MyBatis加载映射文件和动态代理

Java mybatis

机器学习算法(二): 基于鸢尾花数据集的朴素贝叶斯(Naive Bayes)预测分类

汀丶人工智能

数据挖掘 机器学习

卷起来了!阿里最新出品“微服务全阶笔记”,涵盖微服务全部操作

程序员小毕

Java 程序员 微服务 SpringCloud springcloudAlibaba

流批一体在 AI 核心电商领域的探索与实践

Apache Flink

大数据 flink 实时计算

Github点击破百万!这部《从零开始学架构》神书就此霸榜

Java你猿哥

Java 架构 ssm 面经 架构实战

知乎三天点击破亿!四天精通springcloud微服务架构

Java你猿哥

微服务 微服务架构 Spring Cloud 从分层架构到微服务架构

RabbitMQ 延迟消息实战

Java 消息队列 消息中间件 Rabbit MQ

五分钟带你学会微服务熔断原理分析与源码解读

Java你猿哥

微服务 ssm 微服务实战 微服务熔断

独家Java架构师题,面试再不过找我来要赔偿,谢谢

Java你猿哥

架构 面试 ssm 面经 java实战

即时通讯技术文集(第10期):IM通信协议该选TCP还是UDP [共12篇]

JackJiang

大顶堆的实现(基于数组存储的完全二叉树)

Java你猿哥

Java 二叉树 ssm 实战

这一次,NineData新功能上线,真的是拼了

NineData

人工智能 sql 开发规范 数据复制服务 企业开发系统

视频编辑场景下的文字模版技术方案

百度Geek说

企业号 3 月 PK 榜 视频编辑 端渲染 富文本素材

精品!阿里P7爆款《K8s+Jenkins》技术笔记,高质量干货必收藏

Java Kubernetes k8s jenkins

C#/VB.NET:如何将PDF转为PDF/A

在下毛毛雨

C# .net PDF 文档转换 PDF/A

模块9作业

梁山伯

熬了一个月肝完这份阿里P8的Java面试手册,我从20K变成了30K

Java你猿哥

Java 面经 校招 春招 八股文

医疗卫生机构等保测评法律依据有哪些?多久要测评一次?

行云管家

医疗 等保

使用 Metabase 连接 Databend Cloud 实现大屏展示

Databend

简化C#的不可变对象图_后端_Jonathan Allen_InfoQ精选文章