AICon上海|与字节、阿里、腾讯等企业共同探索Agent 时代的落地应用 了解详情
写点什么

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

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

关注

评论

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

安卓系统开发架构!5214页PDF的进阶架构师学习笔记,成功入职腾讯

欢喜学安卓

android 程序员 面试 移动开发

《精通比特币》学习笔记(第八章)

棉花糖

区块链 学习 3月日更

植树节,种个二叉树吧?

悟空聊架构

数据结构 算法 二叉树

力扣(LeetCode)刷题,简单题(第27期)

不脱发的程序猿

面试 LeetCode 28天写作 算法面经 3月日更

细粒度授权在安全领域的重要性

龙归科技

安全 iam 细粒度 ABAC PBAC

翻译:《实用的Python编程》05_01_Dicts_revisited

codists

Python

ECMAScript 2016(ES7)新特性简介

程序那些事

JavaScript ecmascript ES6 程序那些事 es7

数字孪生技术如何实现复制世界?关键的关键是…

华为云开发者联盟

数据中心 数字孪生 节能 仿真 数据中心网图服务

滚雪球学 Python 之闭包操作,本系列第 8 篇文章

梦想橡皮擦

28天写作 3月日更

《未来世界的幸存者》读书笔记

SilentMacUser

极客时间 互联网 技术学习 阅读 阮一峰

一起来学习LiteOS中断模块的源代码

华为云开发者联盟

代码 华为云 LiteOS 中断 中断控制器

你的终端从未如此优雅

Kareza

终端工具 3月日更 Hyper

“新作者 新入驻 新征程”第一季获奖名单

InfoQ写作社区官方

热门活动

真·“拜师学艺”?2021中科院开源之夏,开源大牛1V1&万元奖金只等你来!

京东科技开发者

开源 开源社区

带你了解VXLAN网络中报文的转发机制

华为云开发者联盟

网络 网关 VXLAN 报文 分布式网关

物联网常用协议:MQTT、CoAP、LwM2M、HTTP、LoRaWAN和NB-IoT

不脱发的程序猿

物联网 通信协议 28天写作 3月日更 物联网常用协议

【LeetCode】验证二叉树的前序序列化Java题解

Albert

算法 LeetCode 28天写作 3月日更

你以为在做的是微服务?不!你只是做了个比单体还糟糕的分布式单体!

程序猿DD

微服务

安卓应用程序开发理论!免费Android高级工程师学习资源,附面试题答案

欢喜学安卓

android 程序员 面试 移动开发

与前端训练营的日子 -- Week19

SamGo

学习

关于广东欢太科技可不可信?那是你还不了解

Geek_4a453c

企业 欢太 欢太科技

区块链应用解决方案赋能到农产品溯源上究竟能解决什么问题?

源中瑞-龙先生

硬核!一文学完Flink流计算常用算子(Flink算子大全)

五分钟学大数据

大数据 flink 28天写作 3月日更

对标阿里P9Java架构师面试题,已助我拿下字节、蚂蚁、滴滴三家Offer

Java架构追梦

Java 阿里巴巴 架构 面试 滴滴

寻找被遗忘的勇气(十二)

Changing Lin

3月日更

“种”下黑科技,守护每株绿,“植”了!

华为云开发者联盟

华为 AI IoT modelarts 森林

如何成为一名架构师?

xcbeyond

程序人生 方法论 架构师 成长与思考 3月日更

聊聊什么是CommonJs和Es Module及它们的区别

蛙人

大前端 js ES6

一步一步教你如何在Centos7中配置Kafka运行时环境

happlyfox

28天写作 3月日更

华云大咖说 | 华云数据与瀚高软件携手共建国产云生态 助力政企用户安全可靠发展

华云数据

2月大事件:度目CM-Mini智能面板机全新发布,飞桨PaddleGAN“复活”李焕英

百度大脑

百度 百度大脑

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