我在理解C#中新的Span<T>的用法方面遇到了困难。
它替代了哪些结构?ArraySegment<T>现在已经过时了吗?
它提供了哪些以前没有的功能?
在哪些情况下,Span<T>可以有效地替代C#数组?在哪些情况下不行?
什么时候应该使用ArraySegment<T>而不是Span<T>?
我正在尝试理解如何改变我的编码风格以有效地使用新的Span<T>。
我在理解C#中新的Span<T>的用法方面遇到了困难。
它替代了哪些结构?ArraySegment<T>现在已经过时了吗?
它提供了哪些以前没有的功能?
在哪些情况下,Span<T>可以有效地替代C#数组?在哪些情况下不行?
什么时候应该使用ArraySegment<T>而不是Span<T>?
我正在尝试理解如何改变我的编码风格以有效地使用新的Span<T>。
Span<T>
不是替代任何东西,而是增加了价值。它提供了一种类型安全的方式来查看连续的内存段,可以通过多种方式分配内存:可以分配为托管数组、基于堆栈的内存或非托管内存。
ArraySegment<T>
仅限于托管数组。您无法使用它来包装使用stackalloc
在堆栈上分配的数据。 Span<T>
允许您这样做。
ArraySegment<T>
也无法提供对底层数组的只读视图。 ReadOnlySpan<T>
可以提供这个功能。
Span<T>
并不是要替换数组。归根结底,它只是对数据的一个视图。这些数据必须以某种方式分配,在托管世界中,对于大多数情况,这种分配将是一个数组分配。因此,您仍然需要数组。
如果你想让你的代码能够操作不止数组,那么你应该使用Span<T>
。例如,考虑一个解析库。现在,为了使其能够与数组、堆栈分配的内存和非托管内存一起使用,它必须为每个情况提供多个API入口点,并使用不安全的代码来实际操作数据。它可能还需要公开一个基于string
的API,供那些将数据分配为字符串的人使用。有了Span
和ReadOnlySpan
,您可以将所有这些逻辑合并到单个基于Span
的解决方案中,在所有这些情况下都适用。
Span<T>
并不是每个人都会经常使用的东西。它属于.NET框架中非常专业化的部分,主要对库作者和在高性能关键场景下有用。例如,ASP.NET Core后面的Web服务Kestrel将从使用Span<T>
获得很多性能优势,因为例如可以使用Span<T>
和栈分配的内存来解析请求,这不会对GC施加压力。但是,如果你编写基于ASP.NET Core的网站和服务,不一定需要使用它。
来自MSDN杂志:Span的定义使得操作可以像数组一样高效: 对Span进行索引不需要计算出指针的开头和其起始偏移量,因为ref字段本身已经封装了这两个信息。(相比之下,ArraySegment有一个单独的偏移字段,这使得对其进行索引和传递都更加昂贵。)
另外,虽然ArraySegment实现了IEnumerable
,但Span没有。
ArraySegment
只适用于某些数据结构(如数组)的片段吗?Span
是否也受到相同限制? - mjwills