1. ホーム
  2. c#

[解決済み] C# 7.2でのSpan<T>とMemory<T>の違いは何ですか?

2023-06-01 01:24:40

質問

C# 7.2 では、2 つの新しい型が導入されました。 Span<T>Memory<T> のような以前のC#の型よりもパフォーマンスが向上しています。 string[] .

質問です。の違いは何ですか? Span<T>Memory<T> ? なぜどちらかを使わなければならないのでしょうか?

どのように解決するのですか?

Span<T> はスタックオンリーの性質を持っていますが Memory<T> はヒープ上に存在することができます。

Span<T> は、私たちがプラットフォームに追加した、任意のメモリの連続した領域を表すための新しい型です。 任意のメモリの連続した領域を表現するために、プラットフォームに追加する新しい型です。 T[] と同等のパフォーマンス特性を備えています。その API は配列に似ています。 しかし、配列とは異なり、マネージドメモリ、ネイティブメモリ、またはスタック上に割り当てられたメモリを指すことができます。 スタック上に確保されたメモリを指すことができます。

Memory <T> は型を補完する Span<T> . そのデザインドキュメントで説明されているように のドキュメントで説明されています。 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's OK as Memory<T> is
                       // just like any other type.
    buffer.Span[0] = 1;
}

<ブロッククオート

上記のサンプルでは Memory <byte> はバッファを表すのに使われています。 これは通常の型であり、非同期呼び出しを行うメソッドで使用することができます。 を呼び出すメソッドで使用できます。Spanプロパティは Span<byte> を返しますが、返された値 非同期呼び出しの間、返された値はヒープに保存されず、むしろ から新しい値が生成される。 Memory<T> の値から生成される。ある意味で Memory<T> のファクトリーであり Span<T> .

参考資料です。 こちら