What is the difference between Span<T> and Memory<T> in C# 7.2?

大兔子大兔子 提交于 2019-12-02 16:06:18
Hussein Salman

Span<T> is stack-only in nature while Memory<T> can exist on the heap.

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>.

Reference Document: here

Krzysztof Cwalina

re: this means it can only point to memory allocated on the stack.

Span<T> can point to any memory: allocated either on the stack or the heap. Stack-only nature of Span<T> means that the Span<T> itself (not the memory it points to) must reside only on the stack. This is in contrast to "normal" C# structs, that can reside on the stack or on the heap (either via value-type boxing, or when they are embedded in classes/reference-types). Some of the more obvious practical implications are that you cannot have a Span<T> field in a class, you cannot box Span<T>, and you cannot make an array of them.

Olivier Duhart

Memory<T> can be seen as an unsafe but more versatile version of Span<T>. Access to a Memory<T> object will fail if it points to a freed array.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!