关于 Span 的一切:探索新的 .NET 明星: 2. Span<T> 是如何实现的?

2. Span<T> 是如何实现的?

https://docs.microsoft.com/en-us/archive/msdn-magazine/2018/january/csharp-all-about-span-exploring-a-new-net-mainstay#how-is-spant-implemented

内容列表:

通常开发人员并不需要理解其使用的库是如何实现的。不过,对于 Span<T> 来说,它值得至少理解它后面的细节,因为这些细节影响到它的性能和使用方式的约束。

首先,Span<T> 是包含一个 ref 和长度的值类型,参考定义如下:

public readonly ref struct Span<T>
{
  private readonly ref T _pointer;
  private readonly int _length;
  ...
}

ref T 字段的概念在一开始可能奇怪 - 但是,在 C# 中并不能实际定义 ref T 字段,甚至在 MSIL 中。但是 Span<T> 实际上被开发用来使用运行时的特定内部类型,可以被看作 JIT,使用 JIT 生成等价的 ref T 字段。考虑更为常见的 ref 用法:

public static void AddOne(ref int value) => value += 1;
...
var values = new int[] { 42, 84, 126 };
AddOne(ref values[2]);
Assert.Equal(127, values[2]);

这段代码通过引用传递数组中的一个位置,这样你得到一个在堆栈上的 ref T。该 Span<T> 与 ref T 是相同的思想,简单地在 struct 中封装。直接包含此类 ref 或者间接包含的类型被称为仿 ref 类型,C# 7.2 编译器使用 ref struct 签名来定义此类仿 ref 类型。

通过该总结,明确了两件事:

  1. 通过这种方式定义的 Span ,可以与数组一样高效:对 Span 的索引不需要从指针和其开始位置开始计算,因为 ref 字段已经封装了它们。( 相反,ArraySegment 有独立的 offset 字段,使得它在索引访问和分发时都变得更为昂贵 )
  2. Span 的本质是仿 ref 类型,带来了与 ref T 字段一样的约束。

第二个问题带来了有趣的分支,这些分支导致 .NET 包含由 Memory<T> 引导的第二中类型。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值