.NET 包含许多相互关联的类型,这些类型表示任意内存的连续强类型区域。 这些类型的设计目的是允许创建算法,以尽可能避免不必要地复制内存或在托管堆上进行内存分配。 创建它们(通过 Slice
、 AsSpan()
集合表达式或其构造函数)并不涉及复制基础缓冲区:只会更新表示已包装内存的“视图”的相关引用和偏移量。 在高性能代码中,span 通常用于避免不必要地分配字符串。
类型包括:
System.Span<T>,用于访问连续内存区域的类型。 Span<T> 实例可由一组
T
类型、一个使用 stackalloc 分配的缓冲区或一个指向非托管内存的指针提供支持。 由于必须在堆栈上分配它,因此存在许多限制。 例如,类中的字段不能是Span<T>类型,也不能在异步操作中使用span。System.ReadOnlySpan<T>,Span<T> 结构的不可变版本。 实例还可以由 String 提供支持。
System.Memory<T>:连续内存区域的包装器。 Memory<T>实例可以由类型为
T
的数组或内存管理器支持。 由于它可以存储在托管堆上, Memory<T> 因此没有限制 Span<T>。System.ReadOnlyMemory<T>,Memory<T> 结构的不可变版本。 实例还可以由 String 提供支持。
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.Buffers 命名空间。
使用内存和跨度
由于内存相关类型和跨度相关类型通常用于在处理管道中存储数据,因此在使用Span<T>、Memory<T>及相关类型时,必须遵循一组最佳做法。 这些最佳做法记录在 内存<T> 和跨度<T> 使用指南中。