速来报名!AICon北京站鸿蒙专场~ 了解详情
写点什么

C#的未来:托管指针

  • 2015-05-05
  • 本文字数:1388 字

    阅读完需:约 5 分钟

对于许多开发者,尤其是编写游戏软件,以及进行纯数字计算的开发者来说,原始性能是程序的重中之重。同时对他们来说,最大的问题莫过于内存分配了。虽然分配操作本身消耗很小,但过多的分配会造成内存的极大压力,并且造成垃圾回收器的执行周期更加频繁。

在堆中分配的内存也会造成缓存的问题。如果你有一个存放引用类型的列表或是数组,它的实际数据与数组本身是分开进行保存的。这意味着你可能不得不浪费更多的缓存线以保存这个数组以及由数组所引用的对象。而如果我们在同一时间内创建了这些对象,那么可能会造成很大的分散性,进而导致消耗更多的缓存线。相关数据的分散性也就导致了糟糕的局部性(locality)。

使用值类型(在 C#的说法中也就是结构体)能够极大地减少内存的分配次数并改善局部性。但是,在结构体的使用上存在着一些限制。因为设计它们的初衷是传递拷贝,因此你必须保证它们的尺寸非常小,否则就很可能受到性能上的严惩,这也违背了在第一时间使用值类型的本意。

为了避免无意义的拷贝,一种做法是在将值类型传递给函数时使用一个托管指针。目前为止,唯一一种能够在 C#中创建托管指针的做法是在参数前使用“ref”关键字。这种做法确实能够应对某些场景的性能问题,但实际上 CLR 通过托管指针能够实现的功能远不止这些。

Ref 返回值与 Ref 本地变量这条提议中,提出了另外两种能够为 C#程序员所用的选项。

Ref 本地变量

假设有一个 int 类型的本地变量 a,这条提议允许你通过以下语法创建一个 Ref 本地变量:

ref int x = a;

类似于 ref 参数,ref 本地变量本质上就是它所指代的本地变量的某个别名而已,这种方式使你不必再生成它的拷贝。你也可以通过这种语法创建一个指向某个数组元素、或指向另一个对象的某个字段的指针。

ref int y = b[2];
ref int z = c.d;

在 CLR 术语中,Ref 本地变量被称为一个“TypedReference”(类型化引用)。一个 TypedReference 包含了指向某个地址的指针,同时也包含了该地址所能够存放的数据的类型信息。

按规定,一个 TypedReference 必须是一个参数或本地变量。这一规定是因为 CLR 不允许堆中的元素指向其它元素的内部。你也无法返回一个 TypedReference 对象,否则你就可以返回一个对本地对象的引用,而这个对象在函数结束后自然是已经不存在了。

Ref 返回值

这条提议的第二部分允许你在函数中返回 ref 引用,这就使以下场景变得可能:

public static ref TValue Choose(
Func condition, ref TValue left, ref TValue right)
{
return condition() ? ref left : ref right;
}
Matrix3D left = […], right = […];
Choose(chooser, ref left, ref right).M20 = 1.0;

通过使用这种新语法,以上的示例代码就不会对结构体进行任何拷贝操作,而是创建托管指针并在方法调用中进行传递。

与 ref 本地变量不同,要实现这一特性或许必须对 CLR 标准进行改动。正如之前所说,通常来说是不允许返回 TypedReference 对象的。从技术上讲你可以这么做,但这种操作不是类型安全的,其结果也是“无法检验的”。在受限安全设置中,使用未经检验的代码是不允许的,因为它可能会引起严重的 bug,因此一般只在 C 与 C++ 中使用。

为了缓解这一风险,这条提议中也表示,你所返回的引用必须指向堆中的某个对象,或是指向某个已经存在的 ref 或 out 参数。换句话说,编译器将强迫你不能够返回某个指向本地变量的引用。

查看英文原文: C# Futures: Managed Pointers

2015-05-05 09:572850
用户头像

发布了 428 篇内容, 共 178.6 次阅读, 收获喜欢 38 次。

关注

评论

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

真·workshop,来自联通、移动、爱奇艺等14位资深专家与你面对面聊云原生硬核技术|2022云栖大会

OpenAnolis小助手

云原生 虚拟化 云栖大会 龙蜥社区 专场

分析服务用多维度、多场景的用户分层,带您深度玩转精细化游戏运营

HarmonyOS SDK

分析

华为架构师亲手操刀,世界五百强都在用的kafka也就那么回事

程序知音

Java kafka 架构 后端技术

工作四年,靠这份Java面试宝典,跳槽到阿里,月薪直涨12K

收到请回复

Java 面试 语言 & 开发 金九银十

ElasticSearch + Kibana for Kubernetes 硬气功实践 2

CTO技术共享

elasticsearch 个人成长 10月月更

团队实现知识管理,先从知识库做起!

Baklib

效率 效率工具 知识管理 团队 知识

长安链源码分析之网络模块 net-liquid(7)

SUSE 推出业界首个自适应 Linux 平台原型

Anthony

Linux 自适应

秒云入选2022年成都市新经济梯度培育企业

MIAOYUN

成都市新经济梯度培育企业

SAP | abap的数据对象

暮春零贰

SAP 10月月更 数据对象

知识经济时代,企业该如何进行知识管理?

Baklib

效率工具 知识管理 企业 知识 知识经济

30+场技术论坛 1000+科技新品发布 今年云栖大会我们关注什么?

阿里技术

云栖大会

navicat的使用与数据库的DML操作

渔戈

MySQL SQL语句 10月月更

邂逅Vue3

渔戈

前端 Vue3 10月月更

文本识别与检测-【技术白皮书】第三章-第二节: 基于分割的场景文本检测方法

合合技术团队

人工智能 神经网络 文字识别 自然语言理解

手把手完成智慧路灯的开发,完成设备上云【华为云IoT】

DS小龙哥

10月月更

Kubernetes fror Flink 硬气功实践

CTO技术共享

flink 个人成长 10月月更

Vue模板是怎样编译的

yyds2026

Vue

长安链源码分析之网络模块 net-liquid(6)

分布式事务-引出分布式事务

zarmnosaj

10月月更

打破汽车零部件企业供应链壁垒,数商云SCM供应链系统实现一体化采购协同

数商云

数字化转型 供应链 企业数字化

NFT卡牌链游系统开发Web3游戏技术

薇電13242772558

dapp web3

手把手教你成为荣耀开发者:如何进行注册与认证?

荣耀开发者服务平台

开发者 手机 新手指南 荣耀 honor

【Java深入学习】一个关于“锁”的程序-上

Geek_65222d

10月月更

Vue组件是怎样挂载的

yyds2026

Vue

戴尔Precision 3660工作站:设计师手里的金刚钻

科技热闻

EMQ x 阿里云:云上高效构建,IoT 数据一站处理|直播预告

阿里云弹性计算

物联网 IoT 计算巢

外包和自研应该选择呢?教你三招选出最合适自己的平台

千锋IT教育

ERP外贸管理系统是什么?哪家好?如何选?

优秀

外贸管理 ERP系统 ERP外贸管理系统

Vue3的基本指令

渔戈

前端 Vue3 10月月更

开源日志收集 肿么选型??

CTO技术共享

个人成长 log 10月月更

C#的未来:托管指针_.NET_Jonathan Allen_InfoQ精选文章