内存和跨度相关类型
从 .NET Core 2.1 开始,.NET 包含多个相互关联的类型,它们表示任意内存的相邻强类型区域。 这些方法包括:
System.Span<T>,用于访问连续内存区域的类型。 Span<T> 实例可由一组
T
类型、一个 String、一个使用 stackalloc 分配的缓冲区或一个指向非托管内存的指针提供支持。 由于它必须在堆栈上进行分配,因此存在诸多限制。 例如,类中的字段不能是 Span<T> 类型,跨度类型也不能在异步操作中使用。System.ReadOnlySpan<T>,Span<T> 结构的不可变版本。
System.Memory<T>:连续内存区域的包装器。 Memory<T> 实例可以由
T
类型数组、String 或内存管理器提供支持。 因为 Memory<T> 可以存储在托管堆上,所以它没有任何 Span<T> 限制。System.ReadOnlyMemory<T>,Memory<T> 结构的不可变版本。
System.Buffers.MemoryPool<T>,它将强类型内存块从内存池分配给所有者。 IMemoryOwner<T> 实例可以通过调用 MemoryPool<T>.Rent 从池中租用,并通过调用 MemoryPool<T>.Dispose() 将其释放回池中。
System.Buffers.IMemoryOwner<T>,表示内存块的所有者并控制其生存期管理。
MemoryManager<T>,一个抽象基类,可用于替换 Memory<T> 的实现,以便 Memory<T> 可以由其他类型(如安全句柄)提供支持。 MemoryManager<T> 适用于高级方案。
ArraySegment<T>,从特定索引开始的特定数量数组元素的包装器。
System.MemoryExtensions,用于将字符串、数组和数组段转换为 Memory<T> 块的扩展方法集合。
System.Span<T>、System.Memory<T> 及其只读对等体被设计为,允许创建算法来避免不必要地复制内存或在托管堆上进行分配。 创建它们(通过 Slice
或它们的构造函数)并不涉及复制基础缓冲:只更新代表已包装内存的“视图”的相关引用和偏移。
注意
对于早期框架,Span<T> 和 Memory<T> 在 System.Memory NuGet 包中提供。
有关更多信息,请参见 System.Buffers 命名空间。
使用内存和跨度
由于内存和跨度相关类型通常用于在处理管道中存储数据,因此开发人员在使用 Span<T>、Memory<T> 和相关类型时要务必遵循一套最佳做法。 内存<T> 和跨度<T> 使用准则中介绍了这些最佳做法。