50万奖金+官方证书,深圳国际金融科技大赛正式启动,点击报名 了解详情
写点什么

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

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

关注

评论

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

Alibaba内部晋升手册面试题集 ,Java岗位

Java架构之路

Java 程序员 架构 面试 编程语言

第二周作业

大熊猫

惊艳全网!阿里人开源了K8s进阶宝典笔记,从理论到实践!

996小迁

Java 编程 架构 面试 k8s

还不知道简历如何写?就该这样写!

yes

面试 简历

新世界的智能,旧梦中的暖气

脑极体

第二周作业

纳豆卡玛

第二周作业

喜报丨京东科技主导的开源项目ShardingSphere荣登报告榜单国人主导开源项目中活跃度第五名!

京东科技开发者

分布式数据库 京东 ShardingSphere

席卷图文学习前端Flex布局

我是哪吒

html 面试 大前端 html/css Flex

张红珊—第二章作业

zzz

香喷喷!2021最新出炉Java程序员面试全方位贴身指南

比伯

Java 编程 程序员 架构 面试

训练营-第二周作业

💥萝贝桃儿

产品训练营第二周作业-利益相关者

jpcr987i

MapReduce练习案例3 - 自定义分区

小马哥

大数据 hadoop mapreduce 七日更

MapReduce博文体系

小马哥

大数据 mapreduce 知识体系 架构师 七日更

2021 年产品训练营 - 第二周作业

Meng

在质量管理中掘金

L3C老司机

作业

Eva

Mybatis系列全解(七):全息视角看Dao层两种实现方式之传统方式与代理方式

潘大壮

Java 后端 mybatis mybatis源码

混合云管平台openkube日志系统介绍

太牛了!这是什么神仙级的面试pdf(含答案),跳槽大厂不是问题

Java架构之路

Java 程序员 架构 面试 编程语言

产品经理训练营第二周作业 - 利益相关方

Denny-xi

产品经理 产品经理训练营

产品经理训练营 第二周作业记录

周玲

产品思维 产品经理训练营

第三周作业 利益相关方排序

Eva

产品经理训练营-第二周作业

懒杨杨

产品经理训练营 Week2 作业

Mai

Hadoop之HDFS 内部机制知多少?

hanke

大数据 hadoop hdfs 开源 数据存储

小程序抽奖助手产品利益相关者分析

夏天的风

产品经理训练营

奥里给,通过这几份PDF,终于拿到了阿里,腾讯等一线大厂的offer

Java架构之路

Java 程序员 架构 面试 编程语言

极客大学·产品经理训练营·第二章作业

二大爷

产品经历

Mybatis系列全解(六):Mybatis最硬核的API你知道几个?

潘大壮

Java 后端 mybatis mybatis源码

第二次作业&第三次作业

yoki

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