写点什么

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

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

关注

评论

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

6 种事件驱动的架构模式,springboot入门书籍

Java 程序员 后端

6月GitHub上最牛逼的10个Java开源项目,号称“Star收割机

Java 程序员 后端

7年Java开发经验,面试20多家公司,砍下16个Offer

Java 程序员 后端

Alibaba内部流行的“Java突击宝典”,springboot模块化架构

Java 程序员 后端

avatar Logo,nginx负载均衡算法及原理

Java 程序员 后端

21道Java基础面试题及答案,Dubbo SPI及自适应扩展原理

Java 程序员 后端

浅谈如何实现自定义的 iterator 之二

hedzr

c++ stl Iterator 迭代器

as-if-serial规则和happens-before规则的区别

Java 程序员 后端

Binder源码阅读指南之java层,Java程序员如何有效提升学习效率

Java 程序员 后端

架构实战营模块二作业

随风King

「架构实战营」

CDH+Kylin三部曲之二:部署和设置,java项目百度网盘

Java 程序员 后端

apollo在Spring boot加载过程解析,redis单线程原理

Java 程序员 后端

BAT大厂Java面试必备:20道最新JVM面试题(含答案

Java 程序员 后端

20年IT农民工终于分享出了SpringCloud微服务架构实战文档,太强了!

Java 程序员 后端

90行代码,15个元素实现无限滚动,吃透这份Java高级工程师面试497题解析

Java 程序员 后端

4个实验,彻底搞懂TCP连接的断开,实战nginx张宴

Java 程序员 后端

21道Java基础面试题及答案(1),linux系统管理技术手册

Java 程序员 后端

28天读完349页,这份Alibaba面试通关手册,助我

Java 程序员 后端

6年拉力工作经验,学了阿里P8级架构师的7+1,java基础学习百度云

Java 程序员 后端

97 道大厂 Java 核心面试题出炉,来试试看你会几道题?

Java 程序员 后端

【架构实战营】模块二作业

liu🍊

MacBook M1 搭建OpenVINO环境

IT蜗壳-Tango

OpenVINO MacBook M1 10月月更

5种可能在10年后消失的开发语言,java消息队列面试题

Java 程序员 后端

95% 的算法都是基于这 6 种算法思想,大厂Java面试必考点

Java 程序员 后端

30岁程序员裸辞,闭关三月,拿下阿里字节百度等12家offer

Java 程序员 后端

30张图带你分析:spring事务源码,mysql基础教程视频

Java 程序员 后端

4年Java开发经验,从传统公司裸辞之后足足准备了3个月,终于拿到美团

Java 程序员 后端

985应届进大厂,后端开发两年被裁,对前路迷茫的我

Java 程序员 后端

apiserver源码分析——启动流程,java工程师技术栈

Java 程序员 后端

CAS都不了解,你还怎么看J-U-C,下载量瞬秒百万

Java 程序员 后端

CentOS部署Harbor镜像仓库,java进阶训练营百度网盘

Java 程序员 后端

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