我无法概念化C#中新Span的用法.
它取代了哪些结构?ArraySegment现在已经过时了吗?
以前不支持哪些功能?
Span是C#Arrays的有效替代品吗?在哪些情况下是,在哪些情况下没有?
我何时使用ArraySegment而不是Span?
我试图了解我的编码样式将如何更改以有效使用新的Span.
Mar*_*zek 28
Span<T>
不会取代任何东西.这是增值.它提供了对连续内存段的类型安全视图,可以以多种不同方式分配:作为托管阵列,基于堆栈的内存或非托管内存.
ArraySegment<T>
仅限于托管数组.您不能使用它来包装在堆栈上分配的数据stackalloc
.Span<T>
允许你这样做.
ArraySegment<T>
也没有提供底层数组的只读视图.ReadOnlySpan<T>
给你这个.
Span<T>
不应该替换数组.在一天结束时,它只是一个数据视图.必须以某种方式分配该数据,并且在托管世界中,在大多数情况下,分配将是数组分配.所以你仍然需要数组.
Span<T>
如果您希望代码能够操作的不仅仅是数组,那么您应该使用它.例如,考虑一个解析库.现在,为了允许它使用数组,堆栈分配的内存和非托管内存,它必须在API中为每个内容提供多个入口点,并使用不安全的代码来实际操作数据.它也可能需要公开一个string
基于API的API,供将数据分配为字符串的人使用.使用Span
和ReadOnlySpan
您可以将所有逻辑合并到一个Span
基于单一的解决方案中,该解决方案将适用于所有这些方案.
Span<T>
绝对不会是每个人都经常使用的东西.它是.NET框架的一个高度专业化的部分,主要用于库作者和非常高性能的关键场景.例如,Kestrel,ASP.NET Core后面的Web服务将从移动到中获得很多性能优势,Span<T>
因为例如解析请求可以使用Span<T>
和堆栈分配的内存来完成,这对GC没有任何压力.但是,编写基于ASP.NET Core的网站和服务并不一定非必须使用它.
在决定是否使用 Span 时还要考虑适用于 C# 中的ref 结构的限制:
https://docs.microsoft.com/en-us/dotnet/api/system.span-1?view=netcore-2.2
Span 是一个ref 结构,它在堆栈上而不是在托管堆上分配。Ref struct 类型有许多限制以确保它们不能被提升到托管堆,包括它们不能被装箱,它们不能被分配给 Object、dynamic 或任何接口类型的变量,它们可以'不是引用类型中的字段,并且它们不能跨 await 和 yield 边界使用。此外,调用 Equals(Object) 和 GetHashCode 这两个方法会抛出 NotSupportedException。
重要的
由于它是仅堆栈类型,因此 Span 不适用于许多需要在堆上存储对缓冲区的引用的场景。例如,对于进行异步方法调用的例程来说,情况确实如此。对于此类场景,您可以使用免费的 System.Memory 和 System.ReadOnlyMemory 类型。
对于表示不可变或只读结构的跨度,请使用 System.ReadOnlySpan。
将 ref 修饰符添加到结构声明定义该类型的实例必须被堆栈分配。换句话说,这些类型的实例永远不能作为另一个类的成员在堆上创建。此功能的主要动机是 Span 和相关结构。
将 ref struct 类型保留为堆栈分配变量的目标引入了编译器对所有 ref struct 类型强制执行的几条规则。
- 你不能装箱一个 ref 结构。
- 您不能将 ref struct 类型分配给类型为 object、dynamic 或任何接口类型的变量。
- ref 结构类型不能实现接口。
- 您不能将 ref struct 声明为类或普通 struct 的成员。
- 您不能在异步方法中声明属于 ref 结构类型的局部变量。您可以在返回 Task、Task 或 Task-like 类型的同步方法中声明它们。
- 您不能在迭代器中声明 ref struct 局部变量。
- 您不能在 lambda 表达式或局部函数中捕获 ref struct 变量。
- 这些限制确保您不会意外地以可能将其提升到托管堆的方式使用 ref 结构。
您可以组合修饰符将结构声明为只读引用。readonly ref struct 结合了 ref struct 和 readonly struct 声明的优点和限制。
归档时间: |
|
查看次数: |
4247 次 |
最近记录: |