C# 7.2 中的 Span<T> 和 Memory<T> 有什么区别?
What is the difference between Span<T> and Memory<T> in C# 7.2?
C# 7.2 引入了两种新类型:Span<T>
和 Memory<T>
,它们比 string[]
.
等早期 C# 类型具有更好的性能
问题:Span<T>
和Memory<T>
有什么区别?为什么我要用一个而不是另一个?
Span<T>
本质上是仅堆栈的,而 Memory<T>
可以存在于堆上。
Span<T>
is a new type we are adding to the platform to represent
contiguous regions of arbitrary memory, with performance
characteristics on par with T[]. Its APIs are similar to the array,
but unlike arrays, it can point to either managed or native memory, or
to memory allocated on the stack.
Memory <T>
is a type complementing Span<T>
. As discussed in its design
document, Span<T>
is a stack-only type. The stack-only nature of
Span<T>
makes it unsuitable for many scenarios that require storing
references to buffers (represented with Span<T>
) on the heap, e.g. for
routines doing asynchronous calls.
async Task DoSomethingAsync(Span<byte> buffer) {
buffer[0] = 0;
await Something(); // Oops! The stack unwinds here, but the buffer below
// cannot survive the continuation.
buffer[0] = 1;
}
To address this problem, we will provide a set of complementary types,
intended to be used as general purpose exchange types representing,
just like Span <T>
, a range of arbitrary memory, but unlike Span <T>
these types will not be stack-only, at the cost of significant
performance penalties for reading and writing to the memory.
async Task DoSomethingAsync(Memory<byte> buffer) {
buffer.Span[0] = 0;
await Something(); // The stack unwinds here, but it's OK as Memory<T> is
// just like any other type.
buffer.Span[0] = 1;
}
In the sample above, the Memory <byte>
is used to represent the buffer.
It is a regular type and can be used in methods doing asynchronous
calls. Its Span property returns Span<byte>
, but the returned value
does not get stored on the heap during asynchronous calls, but rather
new values are produced from the Memory<T>
value. In a sense,
Memory<T>
is a factory of Span<T>
.
参考文档:here
re: 这意味着它只能指向在堆栈上分配的内存。
Span<T>
可以指向任何内存:分配在堆栈或堆上。 Span<T>
的仅堆栈性质意味着 Span<T>
本身(不是它指向的内存)必须仅驻留在堆栈上。这与 "normal" C# 结构相反,后者可以驻留在堆栈或堆上(通过值类型装箱,或者当它们嵌入 classes/reference-types 中时)。一些更明显的实际意义是你不能在 class 中有一个 Span<T>
字段,你不能装箱 Span<T>
,你不能制作它们的数组。
Memory<T>
可以看作是 Span<T>
的不安全但更通用的版本。如果 Memory<T>
对象指向已释放的数组,则访问该对象将失败。
C# 7.2 引入了两种新类型:Span<T>
和 Memory<T>
,它们比 string[]
.
问题:Span<T>
和Memory<T>
有什么区别?为什么我要用一个而不是另一个?
Span<T>
本质上是仅堆栈的,而 Memory<T>
可以存在于堆上。
Span<T>
is a new type we are adding to the platform to represent contiguous regions of arbitrary memory, with performance characteristics on par with T[]. Its APIs are similar to the array, but unlike arrays, it can point to either managed or native memory, or to memory allocated on the stack.
Memory <T>
is a type complementingSpan<T>
. As discussed in its design document,Span<T>
is a stack-only type. The stack-only nature ofSpan<T>
makes it unsuitable for many scenarios that require storing references to buffers (represented withSpan<T>
) on the heap, e.g. for routines doing asynchronous calls.
async Task DoSomethingAsync(Span<byte> buffer) {
buffer[0] = 0;
await Something(); // Oops! The stack unwinds here, but the buffer below
// cannot survive the continuation.
buffer[0] = 1;
}
To address this problem, we will provide a set of complementary types, intended to be used as general purpose exchange types representing, just like
Span <T>
, a range of arbitrary memory, but unlikeSpan <T>
these types will not be stack-only, at the cost of significant performance penalties for reading and writing to the memory.
async Task DoSomethingAsync(Memory<byte> buffer) {
buffer.Span[0] = 0;
await Something(); // The stack unwinds here, but it's OK as Memory<T> is
// just like any other type.
buffer.Span[0] = 1;
}
In the sample above, the
Memory <byte>
is used to represent the buffer. It is a regular type and can be used in methods doing asynchronous calls. Its Span property returnsSpan<byte>
, but the returned value does not get stored on the heap during asynchronous calls, but rather new values are produced from theMemory<T>
value. In a sense,Memory<T>
is a factory ofSpan<T>
.
参考文档:here
re: 这意味着它只能指向在堆栈上分配的内存。
Span<T>
可以指向任何内存:分配在堆栈或堆上。 Span<T>
的仅堆栈性质意味着 Span<T>
本身(不是它指向的内存)必须仅驻留在堆栈上。这与 "normal" C# 结构相反,后者可以驻留在堆栈或堆上(通过值类型装箱,或者当它们嵌入 classes/reference-types 中时)。一些更明显的实际意义是你不能在 class 中有一个 Span<T>
字段,你不能装箱 Span<T>
,你不能制作它们的数组。
Memory<T>
可以看作是 Span<T>
的不安全但更通用的版本。如果 Memory<T>
对象指向已释放的数组,则访问该对象将失败。