新的C#Span<;T>;与排列排序不同<;T>;?
我很难概念化的用法新的C#Span<;T>;与排列排序不同<;T>;?,c#,.net-core,C#,.net Core,我很难概念化的用法 它取代了什么构造?ArraySegment现在过时了吗 它启用了以前没有的哪些功能 Span是C#阵列的有效替代品吗?在哪些情况下是,在哪些情况下否 何时使用ArraySegment而不是Span 我正试图了解我的编码风格需要如何改变才能有效地利用新的Span。Span并不能取代任何东西。这是增值。它提供了对连续内存段的类型安全视图,这些连续内存段可以以多种不同的方式分配:作为托管阵列、基于堆栈的内存或非托管内存 ArraySegment仅限于托管阵列。您不能使用它来包装使用
Span
并不能取代任何东西。这是增值。它提供了对连续内存段的类型安全视图,这些连续内存段可以以多种不同的方式分配:作为托管阵列、基于堆栈的内存或非托管内存
ArraySegment
仅限于托管阵列。您不能使用它来包装使用stackalloc
在堆栈上分配的数据Span
允许您这样做
ArraySegment
也不提供底层数组的只读视图ReadOnlySpan
为您提供了这一功能
Span
不应替换阵列。归根结底,这只是一个数据视图。必须以某种方式分配这些数据,在托管世界中,对于大多数情况,这种分配将是一种数组分配。所以你仍然需要数组
如果希望代码能够处理的不仅仅是数组,那么应该使用Span
。例如,考虑解析库。现在,为了让它能够处理数组、堆栈分配内存和非托管内存,它必须在API中为每个数组、堆栈分配内存和非托管内存提供多个入口点,并使用不安全的代码来实际操作数据。它可能还需要公开一个基于字符串的API,供将数据分配为字符串的人使用。使用Span
和ReadOnlySpan
可以将所有逻辑合并到一个基于Span
的解决方案中,该解决方案将适用于所有这些场景
Span
绝对不是每个人都会经常使用的东西。它是.NET framework的一个高度专业化的部分,主要对库作者和非常高性能的关键场景有用。例如,Kestrel,ASP.NET核心背后的web服务将从迁移到Span
中获得许多性能优势,因为例如,可以使用Span
和堆栈分配的内存来解析请求,这对GC没有压力。但是,基于ASP.NET Core编写网站和服务不需要使用它。From:Span的定义使得操作与数组上的操作一样高效:索引到Span不需要计算来确定指针的起始位置及其起始偏移量,因为ref字段本身已经封装了这两者(相比之下,ArraySegment有一个单独的偏移量字段,这使得索引和传递成本更高。)
此外,虽然ArraySegment实现了IEnumerable
,但Span没有实现 在决定是否使用C#中的引用结构时,还应考虑以下限制:
Span是一个ref结构,在堆栈上分配,而不是在
在托管堆上Ref结构类型对
确保它们不能升级到托管堆,包括
它们不能装箱,也不能分配给类型为的变量
对象、动态或任何接口类型,它们不能是
引用类型,它们不能跨等待和屈服使用
边界。另外,调用两个方法,Equals(Object)和
GetHashCode,抛出NotSupportedException。
重要的
因为它是一种仅用于堆栈的类型,所以Span不适用于许多应用程序
需要在堆上存储对缓冲区的引用的场景。这
例如,对于进行异步方法调用的例程来说是真的。
对于这种情况,您可以使用免费的系统。内存和
System.ReadOnlyMemory类型
对于表示不可变或只读结构的跨距,请使用
System.ReadOnlySpan
将ref修饰符添加到结构声明中可定义该实例
必须为该类型分配堆栈。换言之
这些类型永远不能作为其他类型的成员在堆上创建
班级。此功能的主要动机是广度和相关性
结构
将ref struct类型保留为堆栈分配变量的目标
介绍编译器对所有ref结构强制执行的几个规则
类型。
- 您不能框选引用结构。
- 不能将ref struct类型分配给object、dynamic或任何接口类型的变量。
- ref结构类型无法实现接口。
- 不能将ref结构声明为类或普通结构的成员
- 不能在异步方法中声明ref-struct类型的局部变量。您可以在返回Task、Task或类似Task类型的同步方法中声明它们。
- 不能在迭代器中声明ref-struct局部变量。
- 无法在lambda表达式或局部函数中捕获ref struct变量。
- 这些限制确保您不会意外地使用ref结构,从而将其升级到托管堆。
可以组合修饰符将结构声明为只读引用a
只读ref结构结合了ref的优点和限制
结构和只读结构声明
ArraySegment
是否仅限于某些数据结构的一段(例如数组)?Span
是否限制在相同的范围内