写点什么

未来的 C#之只读引用与结构体

  • 2017-04-27
  • 本文字数:1812 字

    阅读完需:约 6 分钟

C++ 中提供了 const 特性,使用该特性定义的参数,其所引用的参数或对象将不会被调用函数修改(当然 const 还提供了更多的特性,参见“ Const 正确性”)。在新的建议中,C#也将提供类似的特性。

只读 ref 参数

在 C#中,“只读引用”也可称为“in 参数”,两者提供了类似的限制。只读引用的基本思想是,如果用“readonly ref”或仅是“in”标注一个参数,那么编译器会解释为“将该参数按引用传递以改进性能,但不允许实际更改该参数”。该特性对于在高性能场景下的大型结构体尤为有用。在建议中引用了如下的例子:

我们知道,在 XNA 等图形库中的向量 / 矩阵数学运算符是具有 ref 操作符的,这纯粹是出于性能上的考虑。Roslyn 编译器本身就有代码使用了结构体,以避免内存分配,并可通过引用的方式传递结构体,免除复制的繁琐。

该语法还结合了 C++ 版本的 const。即参数本身是不可更改的,参数所引用的对象或结构体中的所有数据也是不可更改的。

当前在通过引用传递一个参数时,必须使用“ref”或“out”关键字。在这个建议实现后,使用“in”参数无需受此限制。进而表达式的结果也可以传递进来(当前这在 VB 中是允许的,但是在 C#中尚不允许)。

实现细节

对比“ref”和“out”参数,它们的重载规则具有相同的工作机制。

这依然有待议定,但是当前的计划是不允许“in”参数被匿名函数或 async 函数捕获(即生成一个闭包对象)。捕获“in”参数的问题在于会导致一次拷贝,这破坏了使用“in”参数的初衷,即避免拷贝所导致的性能损耗。

将参数标为“readonly ref”或“in”,并不会令引用值成为不可变值。虽然参数值无法被声明函数更改,但可以在其它地方修改。无需使用多线程,只需能访问参数所引用原始变量的方法即可。

在结构体上调用方法可能会导致问题。在建议中是这样说的:

结构体的所有常规实例方法可转变(mutate)实例,或是对实例暴露引用(ref-expose),因此必须要创建一个临时拷贝,正如当前对接收者是只读域时的做法。

但是,由于没有考虑向后兼容,也不存在变通方案,所以编译器只是给出一个警告,以确保用户留意到这一隐式拷贝。

使用“out”参数时,一个特殊的参数标识了是否需要“in”参数。该参数将被旧的编译器忽略,因此没有向后兼容的问题。

只读 ref 返回

与该特性密切相关的是将 ref returns 标为只读的功能。开发人员使用“in”参数,主要因为它能提供良好的性能,但是“in”参数不允许返回表达式的结果。返回值必须是正常 ref 返回的一个合法变量,其中可以包含数组元素、ref 参数和对象中的域。

ref/in 的扩展方法

“ref”扩展方法将允许扩展方法修改传递进来的结构体。需要编译器能验证传递给 ref 扩展方法的参数是可变的。

虽然“in”扩展方法不允许修改参数,但对于性能敏感的代码依然十分有用,尤其是结构体非常大的时候。这时当然不需要一个可变参数。

在上面两种情况下,该特性只能用于结构体。

编辑按:假定广泛使用了 PureAttribute ,编译器将不允许对“in”扩展方法调用非 PureAttribute 的方法。但由于对性能并无太大改善,因此不大可能广泛应用。

只读结构体

将结构体变量标为 readonly 可能会对性能产生影响。编译器无法确定某个调用是否会对结构体产生改动,因此会默认能够修改,并始终复制只读结构体变量的副本。

使用该特性,开发人员可以在类型层面上将整个结构体标为只读。这样一来,编译器就知道:在通过只读结构体的变量暴露该只读结构体时,不需要进行拷贝。

在建议中指出:

唯一一个显而易见的问题在于:是否需要将其中一些方法改为赋值(mutator)方法。

目前,对只读结构体进行逐个控制只会增加不必要的复杂性,我们可以后期需要时再行添加。

当前,我们假定可变和不可变成员“混合”的结构体并不常见。此外,可变结构体的部分变量通常需要是 LValues,从而避免隐式拷贝的影响。

缺点

建议还指出,这些功能对已有代码不大可能有帮助,但在如下新场景中会很有用,例如:

  • 在计算能力关乎费用,响应能力关乎竞争优势的云场景或数据中心场景下。
  • 对延迟有软性实时需求的游戏 /VR/AR 场景。

在建议中也提出了警告,在“in”参数上的限制可循环作用于被调用函数。但这一问题并不严重,因为已经可以使用“out”参数执行同一操作了。

查看英文原文: C# Futures: Read-Only References and Structs


感谢孙薇对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ @丁晓昀),微信(微信号: InfoQChina )关注我们。

2017-04-27 19:005322
用户头像

发布了 227 篇内容, 共 84.9 次阅读, 收获喜欢 28 次。

关注

评论

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

AI 客服还不够聪明,但已超过月薪五千的人类丨RTE Meetup 回顾

声网

中小企业如何低成本、高效率地启动数智化转型?

万界星空科技

数字化转型 mes 数智化转型 制造业数字化 万界星空科技mes

【Mysql】业务视角下,SQL字段处理专题

LingDong Jey

sql

「从工单困局到智能闭环 —— 一体化运维的革新之路」

智象科技

ITSM IT运维 运维系统 一体化运维 工单管理

自动巡检系统实时监测设备性能的“秘密武器”

智象科技

运维 一体化运维 自动化巡检 自动发现

技术文档 | 当 Agent 遇上 Pulsar:如何重构 A2A 协议,玩转事件驱动架构

AscentStream

Agents

区块链Web3项目的开发周期

北京木奇移动技术有限公司

区块链开发 软件外包公司 web3开发

企业出海的第二战场:海外网络舆情

沃观Wovision

出海企业 沃观Wovision 舆情监测系统 海外舆情监测

Krisp 推出对话轮次转换模型,基于纯音频信号;DeepMind 发布世界模型 Genie 3 ,可保持数分钟一致性丨日报

声网

13kB JavaScript实现的MOBA游戏网络同步技术

qife122

JavaScript 游戏开发

世界人工智能大会顺利举办,龙蜥作为首批成员加入GDPS全球开发者先锋社区平台

OpenAnolis小助手

AI 操作系统 龙蜥社区

如何系统提升学生学科竞赛竞争力|北京理工大学医工交叉教学实践分享(6)

ModelWhale

北京理工大学 AI竞赛 学科竞赛

数据信息过载?避免财务规划超负荷运作

智达方通

全面预算管理 预算管理

防止NLP模型更新在特定任务上性能倒退

qife122

机器学习 模型更新

首届Alexa Prize SimBot挑战赛五强揭晓

qife122

人工智能 多模态交互

基于DWT、矢量量化和自动分片的遥感图像半脆弱水印技术

qife122

数字水印 矢量量化

AI正在“掏空”我们的脑子,但方式超出你的想象——慢慢学AI160

AI决策者洞察

人工智能 #深度思考

MySQL 备份利器 Xtrabackup 全解析:从部署到恢复的实战指南

袋鼠云数栈

MySQL 数据库 mysql备份 XtraBackup

龙蜥专家等共同揭秘专有云 OS 安全信任基石重构之道 |《AI 进化论》第二期

OpenAnolis小助手

AI 操作系统 安全可信 专有云 智算时代

AI在实际生成环境中的提效实践

百度Geek说

AI算力平台统一监控方案:让AI算力资源透明化

智象科技

运维 AI算力 一体化运维

智象 ITSM 三大能力,为 IT 服务质量构筑可持续的确定性

智象科技

运维‘ ITSM软件 ITSM解决方案 一体化运维

AI智能体的开发框架

北京木奇移动技术有限公司

AI智能体 软件外包公司 AI技术应用

AI智能体开发的技术方案

北京木奇移动技术有限公司

AI智能体 软件外包公司 AI技术应用

叮!请接收你的 2025 云栖大会龙蜥社区邀请函

OpenAnolis小助手

AI 操作系统 云栖大会 龙蜥社区 OpenAnolis

Valkey 单点性能比肩 Redis 集群了?Valkey8.0 新特性分析|得物技术

得物技术

redis Redis 核心技术与实战 数据库· valkey

长连接网关技术专题(十三):基于Netty的携程高性能网关异步改造实践

JackJiang

网络编程 即时通讯 IM

金融级 ZooKeeper 来袭:性能提升100%,SLA 99.99%,数据防护升级

阿里巴巴云原生

zookeeper 阿里云 云原生

告警自动化处理:让运维工作更高效、更省心

智象科技

自动化 告警设置 IT运维 一体化运维

未来的C#之只读引用与结构体_.NET_Jonathan Allen_InfoQ精选文章