Подтвердить что ты не робот

В чем разница между Span <T> и Memory <T> в С# 7.2?

В С# 7.2 представлены два новых типа: Span<T> и Memory<T>, которые имеют лучшую производительность по сравнению с более ранними типами С#, такими как string[].

Вопрос: В чем разница между Span<T> и Memory<T>? Почему я использовал один за другим?

4b9b3361

Ответ 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 of Span<T>.

Справочный документ: здесь

Ответ 2

re: это означает, что он может указывать только на память, выделенную в стеке.

Span<T> может указывать на любую память: выделяется либо в стеке, либо в куче. Только для стека Span<T> означает, что сам Span<T> (а не память, на которую он указывает) может находиться только в стеке. Это контрастирует с "нормальными" структурами С#, которые могут находиться в стеке или в куче (когда они встроены в классы/ссылочные типы). Наиболее очевидные практические последствия заключаются в том, что вы не можете иметь поле Span<T> в классе, вы не можете вставить Span<T>, и вы не можете помещать их внутри массивов.