Gå til indholdet

Span<T> og Memory<T>

Span<T> og Memory<T> er to nyttige strukturer i C#, der hjælper dig med at arbejde med kontinuerlige segmenter af data på en sikker og effektiv måde. Begge strukturer er designet til at forbedre ydeevnen og reducere antallet af kopieringer ved at give dig adgang til data uden at ændre den underliggende hukommelsesstruktur.

Span<T>

Span<T> er en struktur, der repræsenterer et kontinuerligt segment af data, såsom en del af et array eller en streng. Det giver dig mulighed for at arbejde med dette data uden at skulle kopiere det. Span<T> er en værditype og kan kun bruges på stakken, hvilket betyder, at den ikke kan gemmes i en klasse, der kan tilgås fra flere tråde, hvilket øger sikkerheden.

Eksempel på brug af Span<T>:

int[] numbers = new int[] { 1, 2, 3, 4, 5 };
Span<int> slice = numbers.AsSpan().Slice(1, 3);

Info

Span<T> er en stack-allokeret type og kan kun bruges inden for den metode, den er defineret i. Du kan ikke returnere en Span<T> fra en metode eller gemme den i en klassefelter eller struktur. Det er velegnet til at arbejde med midlertidig hukommelse inden for en metode.

Memory<T>

Memory<T> er en struktur, der fungerer på en lignende måde som Span<T>, men den kan bruges både på stakken og på heap’en. Dette gør Memory<T> mere fleksibel, men det kan også betyde, at det er mindre sikkert i visse situationer. Memory<T> er især nyttig, når du arbejder med asynkron kode, hvor du ikke kan garantere, at de underliggende data ikke ændres, mens en operation er i gang.

Eksempel på brug af Memory<T>:

int[] numbers = new int[] { 1, 2, 3, 4, 5 };
Memory<int> slice = numbers.AsMemory().Slice(1, 3);

Info

Memory<T> er en heap-allokeret type og kan bruges på tværs af metoder og gemmes i klassefelter eller strukturer. Det er velegnet til at arbejde med data, der skal deles mellem metoder eller have et længerevarende liv.

Fordele

En af de vigtigste fordele ved at bruge Span<T> og Memory<T> er, at de gør det muligt at undgå unødvendige kopieringer af data. For eksempel, hvis du vil beregne summen af et segment af et array, kan du bruge en Span<T> eller Memory<T> til at repræsentere segmentet og sende det som et argument til en metode, i stedet for at kopiere dataene til et nyt array.

Se følgende:

public static int Sum(int[] numbers)
{
    int sum = 0;
    for (int i = 0; i < numbers.Length; i++)
    {
        sum += numbers[i];
    }
    return sum;
}

int[] myArray = new int[] { 1, 2, 3, 4, 5 };

int startIndex = 1;
int count = 3;
int[] newArray = new int[count];
Array.Copy(myArray, startIndex, newArray, 0, count);

int result = Sum(newArray); // Resultatet er 9 (2 + 3 + 4)

Her skabes et nyt array som sendes som argument. Det kan også skrives som

public static int Sum(Span<int> numbers)
{
    int sum = 0;
    foreach (int number in numbers)
    {
        sum += number;
    }
    return sum;
}

int[] myArray = new int[] { 1, 2, 3, 4, 5 };
Span<int> mySlice = myArray.AsSpan().Slice(1, 3);
int result = Sum(mySlice); // Resultatet er 9 (2 + 3 + 4)

Her slipper man for at skabe et nyt array.

Tip

Span<T> og Memory<T> bruges især også i mere avanceret kode som eksempelvis en metode, der udfører en operation på stakallokerede data (stackalloc operatoren)