Span<T> Структура

Определение

Обеспечивает типобезопасное и безопасное представление непрерывной области произвольной памяти.

generic <typename T>
public value class Span
public readonly ref struct Span<T>
type Span<'T> = struct
Public Structure Span(Of T)

Параметры типа

T

Тип элементов в .Span<T>

Наследование
Span<T>

Комментарии

Span<T> — это структура ссылки , которая выделяется в стеке, а не в управляемой куче. Типы структур ссылок имеют ряд ограничений, чтобы они не могли быть повышены до управляемой кучи, включая их невозможно упаковать, они не могут быть назначены переменным типа Objectили dynamic любому типу интерфейса, они не могут быть полями в ссылочный тип, и они не могут использоваться через await границы.yield Кроме того, вызовы двух методов Equals(Object) и GetHashCodeвызовы NotSupportedException.

Важно!

Так как это тип только для стека, Span<T> не подходит для многих сценариев, требующих хранения ссылок на буферы в куче. Это верно, например, подпрограмм, которые выполняют асинхронные вызовы методов. В таких сценариях можно использовать дополнительные System.Memory<T> и System.ReadOnlyMemory<T> типы.

Для диапазонов, представляющих неизменяемые или доступные только для чтения структуры, используйте System.ReadOnlySpan<T>.

Диапазон<T> и память

A Span<T> представляет непрерывную область произвольной памяти. Span<T> Экземпляр часто используется для хранения элементов массива или части массива. В отличие от массива, Span<T> экземпляр может указывать на управляемую память, собственную память или память, управляемую в стеке. В следующем примере создается Span<Byte> из массива:

// Create a span over an array.
var array = new byte[100];
var arraySpan = new Span<byte>(array);

byte data = 0;
for (int ctr = 0; ctr < arraySpan.Length; ctr++)
    arraySpan[ctr] = data++;

int arraySum = 0;
foreach (var value in array)
    arraySum += value;

Console.WriteLine($"The sum is {arraySum}");
// Output:  The sum is 4950
// Create a span over an array.
let array = Array.zeroCreate<byte> 100
let arraySpan = Span<byte> array

let mutable data = 0uy
for i = 0 to arraySpan.Length - 1 do
    arraySpan[i] <- data
    data <- data + 1uy

let mutable arraySum = 0
for value in array do
    arraySum <- arraySum + int value

printfn $"The sum is {arraySum}"
// Output:  The sum is 4950

В следующем примере создается Span<Byte> объем из 100 байт собственной памяти:

// Create a span from native memory.
var native = Marshal.AllocHGlobal(100);
Span<byte> nativeSpan;
unsafe
{
    nativeSpan = new Span<byte>(native.ToPointer(), 100);
}
byte data = 0;
for (int ctr = 0; ctr < nativeSpan.Length; ctr++)
    nativeSpan[ctr] = data++;

int nativeSum = 0;
foreach (var value in nativeSpan)
    nativeSum += value;

Console.WriteLine($"The sum is {nativeSum}");
Marshal.FreeHGlobal(native);
// Output:  The sum is 4950
// Create a span from native memory.
let native = Marshal.AllocHGlobal 100
let nativeSpan = Span<byte>(native.ToPointer(), 100)

let mutable data = 0uy
for i = 0 to nativeSpan.Length - 1 do
    nativeSpan[i] <- data
    data <- data + 1uy

let mutable nativeSum = 0
for value in nativeSpan do
    nativeSum <- nativeSum + int value

printfn $"The sum is {nativeSum}"
Marshal.FreeHGlobal native
// Output:  The sum is 4950

В следующем примере используется ключевое слово C# stackalloc для выделения 100 байт памяти в стеке:

// Create a span on the stack.
byte data = 0;
Span<byte> stackSpan = stackalloc byte[100];
for (int ctr = 0; ctr < stackSpan.Length; ctr++)
    stackSpan[ctr] = data++;

int stackSum = 0;
foreach (var value in stackSpan)
    stackSum += value;

Console.WriteLine($"The sum is {stackSum}");
// Output:  The sum is 4950
    // Create a span on the stack.
    let mutable data = 0uy
    let stackSpan = 
        let p = NativeInterop.NativePtr.stackalloc<byte> 100 |> NativeInterop.NativePtr.toVoidPtr
        Span<byte>(p, 100)

    for i = 0 to stackSpan.Length - 1 do
        stackSpan[i] <- data
        data <- data + 1uy

    let mutable stackSum = 0
    for value in stackSpan do
        stackSum <- stackSum + int value

    printfn $"The sum is {stackSum}"
// Output:  The sum is 4950

Поскольку Span<T> это абстракция по произвольному блоку памяти, методы Span<T> типа и методов с параметрами работают с Span<T> любым Span<T> объектом независимо от типа памяти, который он инкапсулирует. Например, каждый из отдельных разделов кода, инициализирующих диапазон и вычислив сумму его элементов, можно изменить в одинарные методы инициализации и вычисления, как показано в следующем примере:

public static void WorkWithSpans()
{
    // Create a span over an array.
    var array = new byte[100];
    var arraySpan = new Span<byte>(array);

    InitializeSpan(arraySpan);
    Console.WriteLine($"The sum is {ComputeSum(arraySpan):N0}");

    // Create an array from native memory.
    var native = Marshal.AllocHGlobal(100);
    Span<byte> nativeSpan;
    unsafe
    {
        nativeSpan = new Span<byte>(native.ToPointer(), 100);
    }

    InitializeSpan(nativeSpan);
    Console.WriteLine($"The sum is {ComputeSum(nativeSpan):N0}");

    Marshal.FreeHGlobal(native);

    // Create a span on the stack.
    Span<byte> stackSpan = stackalloc byte[100];

    InitializeSpan(stackSpan);
    Console.WriteLine($"The sum is {ComputeSum(stackSpan):N0}");
}

public static void InitializeSpan(Span<byte> span)
{
    byte value = 0;
    for (int ctr = 0; ctr < span.Length; ctr++)
        span[ctr] = value++;
}

public static int ComputeSum(Span<byte> span)
{
    int sum = 0;
    foreach (var value in span)
        sum += value;

    return sum;
}
// The example displays the following output:
//    The sum is 4,950
//    The sum is 4,950
//    The sum is 4,950
open System
open System.Runtime.InteropServices
open FSharp.NativeInterop

// Package FSharp.NativeInterop.NativePtr.stackalloc for reuse.
let inline stackalloc<'a when 'a: unmanaged> length : Span<'a> =
    let voidPointer = NativePtr.stackalloc<'a> length |> NativePtr.toVoidPtr
    Span<'a>(voidPointer, length)

let initializeSpan (span: Span<byte>) =
    let mutable value = 0uy
    for i = 0 to span.Length - 1 do
        span[i] <- value
        value <- value + 1uy

let computeSum (span: Span<byte>) =
    let mutable sum = 0
    for value in span do
        sum <- sum + int value
    sum

let workWithSpans () =
    // Create a span over an array.
    let array = Array.zeroCreate<byte> 100
    let arraySpan = Span<byte> array

    initializeSpan arraySpan
    printfn $"The sum is {computeSum arraySpan:N0}"

    // Create an array from native memory.
    let native = Marshal.AllocHGlobal 100
    let nativeSpan = Span<byte>(native.ToPointer(), 100)

    initializeSpan nativeSpan
    printfn $"The sum is {computeSum nativeSpan:N0}"

    Marshal.FreeHGlobal native

    // Create a span on the stack.
    let stackSpan = stackalloc 100

    initializeSpan stackSpan
    printfn $"The sum is {computeSum stackSpan:N0}"

// The example displays the following output:
//    The sum is 4,950
//    The sum is 4,950
//    The sum is 4,950

Диапазон<T> и массивы

При переносе массива Span<T> можно упаковать весь массив, как это было в примерах в разделе Span<T> и memory . Так как он поддерживает срезы, Span<T> он также может указывать на любой непрерывный диапазон в массиве.

В следующем примере создается срез среднего пяти элементов целочисленного массива из 10 элементов. Обратите внимание, что код удвоит значения каждого целого числа в срезе. Как показано в выходных данных, изменения, внесенные диапазоном, отражаются в значениях массива.

using System;

var array = new int[] { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 };
var slice = new Span<int>(array, 2, 5);
for (int ctr = 0; ctr < slice.Length; ctr++)
    slice[ctr] *= 2;

// Examine the original array values.
foreach (var value in array)
    Console.Write($"{value}  ");
Console.WriteLine();

// The example displays the following output:
//      2  4  12  16  20  24  28  16  18  20
module Program

open System

[<EntryPoint>]
let main _ =
    let array = [| 2; 4; 6; 8; 10; 12; 14; 16; 18; 20 |]
    let slice = Span<int>(array, 2, 5)
    for i = 0 to slice.Length - 1 do
        slice[i] <- slice[i] * 2

    // Examine the original array values.
    for value in array do
        printf $"{value}  "
    printfn ""
    0
// The example displays the following output:
//      2  4  12  16  20  24  28  16  18  20

Диапазон<T> и срезы

Span<T> включает две перегрузки Slice метода, которые образуют срез из текущего диапазона, который начинается с указанного индекса. Это позволяет обрабатывать данные в Span<T> виде набора логических блоков, которые могут обрабатываться по мере необходимости частями конвейера обработки данных с минимальным влиянием на производительность. Например, так как современные протоколы сервера часто основаны на тексте, особенно важно манипулировать строками и подстроками. String В классе основным методом извлечения подстрок является Substring. Для конвейеров данных, использующих обширные операции со строками, его использование обеспечивает некоторые штрафы производительности, так как они:

  1. Создает новую строку для хранения подстроки.

  2. Копирует подмножество символов из исходной строки в новую строку.

Эту операцию выделения и копирования можно исключить с помощью одного или Span<T> ReadOnlySpan<T>, как показано в следующем примере:

using System;

class Program2
{
    static void Main()
    {
        string contentLength = "Content-Length: 132";
        var length = GetContentLength(contentLength.ToCharArray());
        Console.WriteLine($"Content length: {length}");
    }

    private static int GetContentLength(ReadOnlySpan<char> span)
    {
        var slice = span.Slice(16);
        return int.Parse(slice);
    }
}
// Output:
//      Content length: 132
module Program2

open System

let getContentLength (span: ReadOnlySpan<char>) =
    let slice = span.Slice 16
    Int32.Parse slice

let contentLength = "Content-Length: 132"
let length = getContentLength (contentLength.ToCharArray())
printfn $"Content length: {length}"
// Output:
//      Content length: 132

Конструкторы

Span<T>(T[])

Создает новый объект Span<T> по всему указанному массиву.

Span<T>(T[], Int32, Int32)

Создает новый объект Span<T>, который включает указанное число элементов массива, начиная с указанного индекса.

Span<T>(Void*, Int32)

Создает объект Span<T> из указанного числа элементов T, начиная с заданного адреса памяти.

Свойства

Empty

Возвращает пустой объект Span<T>.

IsEmpty

Возвращает значение, указывающее, пуст ли текущий объект Span<T>.

Item[Int32]

Возвращает элемент по указанному индексу, начинающемуся с нуля.

Length

Возвращает длину текущего диапазона.

Методы

Clear()

Удаляет содержимое этого объекта Span<T>.

CopyTo(Span<T>)

Копирует содержимое этого объекта Span<T> в назначение Span<T>.

Equals(Object)
Является устаревшей.
Является устаревшей.

Вызов этого метода не поддерживается.

Fill(T)

Заполняет элементы диапазона заданным значением.

GetEnumerator()

Возвращает перечислитель для коллекции Span<T>.

GetHashCode()
Является устаревшей.

Создает исключение NotSupportedException.

GetPinnableReference()

Возвращает ссылку на объект типа T, который можно использовать для закрепления.

Этот метод предназначен для поддержки .NET компиляторов и не предназначен для вызова пользовательским кодом.

Slice(Int32)

Формирует срез вне текущего диапазона, который начинается с указанного индекса.

Slice(Int32, Int32)

Формирует срез вне текущей области, начиная с указанного индекса до указанной длины.

ToArray()

Копирует содержимое этого диапазона в новый массив.

ToString()

Возвращает строковое представление конкретного объекта Span<T>.

TryCopyTo(Span<T>)

Пытается скопировать текущий Span<T> в назначение Span<T> и возвращает значение, указывающее, успешно ли выполнена операция копирования.

Операторы

Equality(Span<T>, Span<T>)

Возвращает значение, указывающее, равны ли два объекта Span<T>.

Implicit(ArraySegment<T> to Span<T>)

Определяет неявное преобразование ArraySegment<T> в Span<T>.

Implicit(Span<T> to ReadOnlySpan<T>)

Определяет неявное преобразование Span<T> в ReadOnlySpan<T>.

Implicit(T[] to Span<T>)

Определяет неявное преобразование массива в Span<T>.

Inequality(Span<T>, Span<T>)

Возвращает значение, указывающее, являются ли два объекта Span<T> неравными.

Методы расширения

ToImmutableArray<T>(Span<T>)

Преобразует диапазон в неизменяемый массив.

BinarySearch<T>(Span<T>, IComparable<T>)

Выполняет поиск значения во всем отсортированном массиве Span<T>, используя заданный универсальный интерфейс IComparable<T>.

BinarySearch<T,TComparer>(Span<T>, T, TComparer)

Выполняет поиск указанного значения во всем отсортированном массиве Span<T>, используя заданный универсальный тип TComparer.

BinarySearch<T,TComparable>(Span<T>, TComparable)

Выполняет поиск значения во всем отсортированном массиве Span<T>, используя заданный универсальный тип TComparable.

CommonPrefixLength<T>(Span<T>, ReadOnlySpan<T>)

Находит длину общего префикса, совместно используемого между span и other.

CommonPrefixLength<T>(Span<T>, ReadOnlySpan<T>, IEqualityComparer<T>)

Находит длину общего префикса, совместно используемого между span и other.

Contains<T>(Span<T>, T)

Указывает, найдено ли указанное значение в диапазоне. Значения сравниваются с помощью IEquatable {T}.Equals (T).

EndsWith<T>(Span<T>, ReadOnlySpan<T>)

Определяет, отображается ли указанная последовательность в конце диапазона.

IndexOf<T>(Span<T>, T)

Выполняет поиск указанного значения и возвращает индекс его первого вхождения. Значения сравниваются с помощью IEquatable {T}.Equals (T).

IndexOf<T>(Span<T>, ReadOnlySpan<T>)

Выполняет поиск указанной последовательности и возвращает индекс ее первого вхождения. Значения сравниваются с помощью IEquatable {T}.Equals (T).

IndexOfAny<T>(Span<T>, T, T)

Выполняет поиск первого индекса любого из указанных значений аналогичного вызову IndexOf несколько раз с помощью логического оператора ИЛИ.

IndexOfAny<T>(Span<T>, T, T, T)

Выполняет поиск первого индекса любого из указанных значений аналогичного вызову IndexOf несколько раз с помощью логического оператора ИЛИ.

IndexOfAny<T>(Span<T>, ReadOnlySpan<T>)

Выполняет поиск первого индекса любого из указанных значений аналогичного вызову IndexOf несколько раз с помощью логического оператора ИЛИ.

IndexOfAnyExcept<T>(Span<T>, T)

Выполняет поиск первого индекса любого значения, отличного от указанного value.

IndexOfAnyExcept<T>(Span<T>, T, T)

Выполняет поиск первого индекса любого значения, отличного от указанного value0 или value1.

IndexOfAnyExcept<T>(Span<T>, T, T, T)

Выполняет поиск первого индекса любого значения, отличного от указанного value0, value1или value2.

IndexOfAnyExcept<T>(Span<T>, ReadOnlySpan<T>)

Выполняет поиск первого индекса любого значения, отличного от указанного values.

LastIndexOf<T>(Span<T>, T)

Выполняет поиск указанного значения и возвращает индекс его последнего вхождения. Значения сравниваются с помощью IEquatable {T}.Equals (T).

LastIndexOf<T>(Span<T>, ReadOnlySpan<T>)

Выполняет поиск указанной последовательности и возвращает индекс ее последнего вхождения. Значения сравниваются с помощью IEquatable {T}.Equals (T).

LastIndexOfAny<T>(Span<T>, T, T)

Выполняет поиск последнего индекса любого из указанных значений аналогичного вызову LastIndexOf несколько раз с помощью логического оператора ИЛИ.

LastIndexOfAny<T>(Span<T>, T, T, T)

Выполняет поиск последнего индекса любого из указанных значений аналогичного вызову LastIndexOf несколько раз с помощью логического оператора ИЛИ.

LastIndexOfAny<T>(Span<T>, ReadOnlySpan<T>)

Выполняет поиск последнего индекса любого из указанных значений аналогичного вызову LastIndexOf несколько раз с помощью логического оператора ИЛИ.

LastIndexOfAnyExcept<T>(Span<T>, T)

Выполняет поиск последнего индекса любого значения, отличного от указанного value.

LastIndexOfAnyExcept<T>(Span<T>, T, T)

Выполняет поиск последнего индекса любого значения, отличного от указанного или value1.value0

LastIndexOfAnyExcept<T>(Span<T>, T, T, T)

Выполняет поиск последнего индекса любого значения, отличного от указанного value0, value1или value2.

LastIndexOfAnyExcept<T>(Span<T>, ReadOnlySpan<T>)

Выполняет поиск последнего индекса любого значения, отличного от указанного values.

Overlaps<T>(Span<T>, ReadOnlySpan<T>)

Определяет, перекрываются ли диапазон и диапазон только для чтения в памяти.

Overlaps<T>(Span<T>, ReadOnlySpan<T>, Int32)

Определяет, перекрываются ли диапазон и диапазон только для чтения в памяти, и выводит смещение элементов.

Reverse<T>(Span<T>)

Изменяет порядок элементов во всем массиве на обратный.

SequenceCompareTo<T>(Span<T>, ReadOnlySpan<T>)

Определяет относительный порядок диапазона и диапазона только для чтения путем сравнения их элементов с помощью IComparable{T}.CompareTo (T).

SequenceEqual<T>(Span<T>, ReadOnlySpan<T>)

Определяет, равны ли диапазон и диапазон только для чтения, сравнивая элементы с помощью IEquatable{T}.Equals (T).

SequenceEqual<T>(Span<T>, ReadOnlySpan<T>, IEqualityComparer<T>)

Определяет, равны ли две последовательности путем сравнения элементов с помощью .IEqualityComparer<T>

Sort<T>(Span<T>)

Сортирует элементы целиком Span<T> IComparable<T> с помощью реализации каждого элемента элемента Span<T>.

Sort<T>(Span<T>, Comparison<T>)

Сортирует элементы во всем списке Span<T> с использованием указанного Comparison<T>.

Sort<T,TComparer>(Span<T>, TComparer)

Сортирует элементы во всем Span<T> с использованием TComparer.

Sort<TKey,TValue>(Span<TKey>, Span<TValue>)

Сортирует пару диапазонов (один диапазон с ключами, а второй с соответствующими элементами) на основе ключей в первом Span<T> с использованием реализации IComparable<T> каждого ключа.

Sort<TKey,TValue>(Span<TKey>, Span<TValue>, Comparison<TKey>)

Сортирует пару диапазонов (один диапазон с ключами, а второй с соответствующими элементами) на основе ключей в первом Span<T> с использованием указанного сравнения.

Sort<TKey,TValue,TComparer>(Span<TKey>, Span<TValue>, TComparer)

Сортирует пару диапазонов (один диапазон с ключами, а второй с соответствующими элементами) на основе ключей в первом Span<T> с использованием указанного компаратора.

StartsWith<T>(Span<T>, ReadOnlySpan<T>)

Определяет, отображается ли указанная последовательность в начале диапазона.

Trim<T>(Span<T>, T)

Удаляет все начальные и конечные вхождения указанного элемента из диапазона.

Trim<T>(Span<T>, ReadOnlySpan<T>)

Удаляет все начальные и конечные вхождения набора элементов, указанного в диапазоне только для чтения, из диапазона.

TrimEnd<T>(Span<T>, T)

Удаляет все конечные вхождения указанного элемента из диапазона.

TrimEnd<T>(Span<T>, ReadOnlySpan<T>)

Удаляет все конечные вхождения набора элементов, указанного в диапазоне только для чтения, из диапазона.

TrimStart<T>(Span<T>, T)

Удаляет все начальные вхождения указанного элемента из диапазона.

TrimStart<T>(Span<T>, ReadOnlySpan<T>)

Удаляет все начальные вхождения набора элементов, указанного в диапазоне только для чтения, из диапазона.

Применяется к

См. также раздел