Ответ 1
Span<T>
является только стеком, а Memory<T>
может использовать кучу.
Span<T>
- это новый тип, который мы добавляем к платформе для представления смежные области произвольной памяти с производительностью характеристики наравне с T []. Его API-интерфейсы похожи на массив, но в отличие от массивов, он может указывать либо на управляемую, либо на встроенную память, или в память, выделенную в стеке.
Memory <T>
- это тип, дополняющийSpan<T>
. Как обсуждалось в его проекте document,Span<T>
- тип только для стека. Степ-только характерSpan<T>
делает его непригодным для многих сценариев, требующих хранения ссылки на буферы (представленныеSpan<T>
) в куче, например. для подпрограммы, выполняющие асинхронные вызовы.
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;
}
Чтобы решить эту проблему, мы предоставим набор дополнительных типов, предназначенные для использования в качестве типов обмена общего назначения, представляющие, точно так же, как
Span <T>
, диапазон произвольной памяти, но в отличие отSpan <T>
эти типы не будут только для стека, за счет значительных производительность для чтения и записи в память.
async Task DoSomethingAsync(Memory<byte> buffer) {
buffer.Span[0] = 0;
await Something(); // The stack unwinds here, but it OK as Memory<T> is
// just like any other type.
buffer.Span[0] = 1;
}
В приведенном выше примере для представления буфера используется
Memory <byte>
. Он является обычным типом и может использоваться в методах, выполняющих асинхронные звонки. Свойство Span возвращаетSpan<byte>
, но возвращаемое значение не сохраняется в куче во время асинхронных вызовов, а новые значения производятся из значенияMemory<T>
. В некотором смысле,Memory<T>
является factory ofSpan<T>
.
Справочный документ: здесь