写点什么

简化 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:272267
用户头像

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

关注

评论

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

“懂行”的价值循环与蝴蝶风暴

脑极体

极客大学架构师训练营第一期第八周总结

睡不着摇一摇

架构师一期

【JAVA】TreeSet, LinkedHashSet和HashSet差异对比

笑春风

第八周总结

alpha

极客大学架构师训练营

分分钟玩转SpringBoot自定义注解

比伯

Java 大数据 编程 架构 编程语言

年轻人的第一个MyBatis项目就要这样来学习,不走弯路

小Q

Java 学习 架构 面试 mybatis

python+requests进行get、post方法接口测试

测试人生路

Python 接口测试

成为架构师 - 架构师训练营第 04周

陈永龙Vincent

“区块链+营销”:科技力量助力行业前行

CECBC

市场营销

苏州崛起为我国区块链产业高地

CECBC

区块链 社区矫正

腾讯强推Redis大神之路成长手册!原理+应用+集群+拓展+源码五篇齐飞

Java架构追梦

Java 数据库 redis 架构 面试

《Web应用安全权威指南》.pdf

田维常

架构师训练营第 1 期 - 第八周总结

Todd-Lee

极客大学架构师训练营

架构师训练营 第四周作业

文江

Java8引入新的日期和时间库,你应该知道

Silently9527

java8

高交会:高新企业源中瑞在此出展区块链BAAS技术

13530558032

网络时间协议介绍以及服务器同步网络时间

MySQL从删库到跑路

ntp 时间同步

区块链治理的真实价值在哪里

CECBC

区块链 治理 治理机制

ebay支付核心账务系统架构演进之路

贾奇 (Jacky)

支付系统 共识机制 系统稳定高可用 Event Sourcing 异地多活容灾

第四周作业

Jack

《身边的金钱心理学》

石云升

训练营第四周作业

大脸猫

极客大学架构师训练营

【可下载】2020年底收官!为大家整理了物联网行业全面研究报告、行业洞察、白皮书……

IoT云工坊

人工智能 大数据 5G 物联网 智能家居

第八周课后练习

knight

架构作业--相交链表

Nick~毓

JVM真香系列:图解垃圾回收器

田维常

JVM 垃圾回收

训练营第四周总结

大脸猫

极客大学架构师训练营

【Mycat】Mycat核心开发者带你轻松掌握Mycat路由转发!!

冰河

分布式 微服务 分库分表 中间件 mycat

第八章作业

alpha

极客大学架构师训练营

腾讯强推Redis成长手册!原理+应用+集群+拓展+源码五飞

小Q

Java redis 学习 架构 面试

家谱链亮相高交会,点亮“区块链+文化”融合发展之路

13530558032

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