2017-11-16 44 views
23

C# 7.2 wprowadza dwa nowe typy: Span<T> i Memory<T>, które mają lepszą wydajność w stosunku do wcześniejszych typów C#, takich jak string[].Jaka jest różnica między Span <T> a pamięcią <T> w C# 7.2?

Pytanie: Jaka jest różnica między Span<T> a Memory<T>? Dlaczego miałbym używać jednego nad drugim?

+3

Zobacz też: [C# 7.2: Understanding Span] (https://channel9.msdn.com/Events/Connect/2017/T125) –

+1

@JeffMercado Czy istnieje pełna lista gdzieś z typów C#, które mogą zastąpić poza ciągiem znaków []? Czy są one tylko dla tablic, czy też mogą być używane zamiast typów takich jak Lista ? – user3610374

Odpowiedz

22

Span<T> jest natury stosu, a Memory<T> może korzystać ze sterty.

Span<T> jest nowy typ jest dodanie do peronu stanowią sąsiadujących regionów dowolnego z pamięcią oraz z wykonywaniem cech na równi z T []. Jego interfejsy API są podobne do tablic, , ale w przeciwieństwie do tablic może wskazywać na pamięć zarządzaną lub macierzystą, lub na pamięć przydzieloną na stosie.

Memory <T> to rodzaj uzupełniający Span<T>. Jak omówiono w dokumencie projektu , Span<T> jest typem stosu. Charakter stosu tylko Span<T> powoduje, że nie nadaje się do wielu scenariuszy, które wymagają przechowywania odniesień do buforów (reprezentowanych przez Span<T>) na stercie, np. dla podprogramów wykonujących połączenia asynchroniczne.

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; 
} 

Aby rozwiązać ten problem, będziemy dostarczać zestaw komplementarnych typów przeznaczone do użycia jako typy wymiany ogólnego przeznaczenia reprezentujących, podobnie jak Span <T>, zakresu arbitralne pamięci, ale w przeciwieństwie do Span <T> typy te nie będą składowane tylko na stosie, kosztem znacznych kar za odczytywanie i zapisywanie w pamięci za .

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; 
} 

W próbie powyżej, Memory <byte> służy do reprezentowania bufor. Jest to typ zwykły i może być używany w metodach wykonujących połączenia asynchroniczne . Jego właściwość Span zwraca wartość Span<byte>, ale zwracana wartość nie jest zapisywana na stercie podczas połączeń asynchronicznych, ale nowe wartości są tworzone z wartości Memory<T>. W pewnym sensie, Memory<T> jest fabryką Span<T>.

Referencje dokumentu: here

+1

Co oznacza "charakter tylko do stosu"? – Enigmativity

+0

@Coding, to nie prawda, może również wskazywać na pamięć zarządzaną (np. Tablice). Fakt, że rozpiętość może być tylko w stosie, nie oznacza, że ​​pamięć, na którą wskazuje, również musi znajdować się w stosie. –

+0

Czy możesz przesłać linki do dokumentów projektowych, do których się odwołujesz? –

10

re: to oznacza, że ​​może tylko punkt do pamięci przydzielonej na stosie.

Span<T> może wskazywać dowolną pamięć: przydzieloną na stos lub stertę. Tylko dla stosu o numerze Span<T> oznacza, że ​​sama Span<T> (a nie pamięć, na którą wskazuje) może znajdować się tylko na stosie. Jest to przeciwieństwo "normalnych" struktur C#, które mogą znajdować się na stosie lub na stercie (gdy są osadzone w klasach/typach referencyjnych).Najbardziej oczywiste implikacje praktyczne polegają na tym, że nie można mieć pola Span<T> w klasie, nie można wpisać Span<T> i nie można umieścić ich wewnątrz tablic.

+0

Ah, kolejny z tych typów przypominających byref. – IllidanS4

Powiązane problemy