Span<T> 結構

定義

提供任意記憶體連續區域的類型安全與記憶體安全表示法。

generic <typename T>
public value class Span
[System.Runtime.InteropServices.Marshalling.NativeMarshalling(typeof(System.Runtime.InteropServices.Marshalling.SpanMarshaller<,>))]
public readonly ref struct Span<T>
public readonly ref struct Span<T>
[<System.Runtime.InteropServices.Marshalling.NativeMarshalling(typeof(System.Runtime.InteropServices.Marshalling.SpanMarshaller<,>))>]
type Span<'T> = struct
type Span<'T> = struct
Public Structure Span(Of T)

類型參數

T

項目類型。Span<T>

繼承
Span<T>
屬性

備註

Span<T> 類型是一種 ref 結構 ,配置於堆疊上,而不是在受控式堆積上配置。 Ref 結構類型有一些限制,以確保它們無法被升階到受管理堆積,包括不能被提升到:

  • 裝盒。
  • 指派給型別 Object 為 或 dynamic的變數,或任何介面型別。
  • 欄位屬於參考型態。
  • 跨界awaityield使用。

此外,呼叫兩個方法Equals(Object)GetHashCode會擲回NotSupportedException

Important

因為它是堆疊專用的類型,Span<T> 因此不適合許多需要在堆上儲存緩衝區參考的情境。 例如,這種情況適用於進行異步方法呼叫的例程。 針對這類案例,您可以使用互補 System.Memory<T>System.ReadOnlyMemory<T> 型別。

對於代表不可變或唯讀結構之範圍,請使用 System.ReadOnlySpan<T>

Memory

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

下列範例會從 100 位元組的原生記憶體建立一個 Span<Byte>

// 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

陣列

當它包裝陣列時,Span<T>可以包裝整個陣列,就像記憶體區段中的範例一樣。 因為它支援切割,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

切片

Span<T> 包含兩個 Slice 方法的多載,這些多載會從當前範圍中形成一個從指定索引開始的切片。 這可讓您將Span<T>中的數據視為一組邏輯區塊,在不影響效能的情況下,根據需要處理數據處理流程的一部分。 例如,由於新式伺服器通訊協定通常是以文字為基礎的,因此對字串和子字串的操作特別重要。 在類別中 String ,擷取子字串 Substring的主要方法是 。 對於依賴大量字串操作的數據管線,其使用會造成一些效能損耗,因為它:

  1. 建立新的字串來保存子字串。
  2. 將原始字串中的字元子集複製到新的字串。

您可以使用Span<T>ReadOnlySpan<T>來消除此配置和複製操作,如下列範例所示:

using System;

class Program2
{
    static void Run()
    {
        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

建構函式

名稱 Description
Span<T>(T)

建立一個長度為 1 的新 Span<T> 參考,圍繞指定的參考。

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

建立一個新 Span<T> 物件,包含從指定索引開始的陣列元素數量。

Span<T>(T[])

在整個指定陣列上建立一個新 Span<T> 物件。

Span<T>(Void*, Int32)

從指定記憶體位址開始的指定元素Span<T>數量建立一個新T物件。

屬性

名稱 Description
Empty

回傳一個空 Span<T> 物件。

IsEmpty

回傳一個表示電流 Span<T> 是否為空的值。

Item[Int32]

取得該元素在指定的零基索引處。

Length

回傳當前跨度的長度。

方法

名稱 Description
Clear()

清除此 Span<T> 物件的內容。

CopyTo(Span<T>)

將這些 Span<T> 內容複製到目的地 Span<T>

Equals(Object)
已淘汰.
已淘汰.

不支援呼叫此方法。

Fill(T)

以指定值填滿該跨度的元素。

GetEnumerator()

回傳一個列 Span<T>舉器 。

GetHashCode()
已淘汰.

擲回 NotSupportedException

GetPinnableReference()

回傳一個類型為 T 的物件參考,可用於釘選。

此方法旨在支援 .NET 編譯器,並非使用者程式碼所呼叫。

Slice(Int32, Int32)

從指定索引開始、長度指定的情況下,從當前區間中切出一個切片。

Slice(Int32)

從當前區間中劃出一個切片,起始於指定索引。

ToArray()

將此區間的內容複製到一個新的陣列中。

ToString()

回傳此 Span<T> 物件的字串表示。

TryCopyTo(Span<T>)

嘗試將當前 Span<T> 資料複製到目的地 Span<T> ,並回傳一個表示複製操作是否成功的值。

操作員

名稱 Description
Equality(Span<T>, Span<T>)

回傳一個表示兩個 Span<T> 物件是否相等的值。

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

定義了 的ArraySegment<T>Span<T>隱式轉換 。

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

定義了 a Span<T>ReadOnlySpan<T>式轉換為 。

Implicit(T[] to Span<T>)

定義了陣列 Span<T>隱式轉換為 。

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

回傳一個表示兩個 Span<T> 物件是否不相等的值。

擴充方法

名稱 Description
BinarySearch<T,TComparable>(Span<T>, TComparable)

會用指定的Span<T>通用型別搜尋整個排序TComparable的值。

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

使用指定的Span<T>一般型別搜尋整個排序的TComparer指定值。

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

使用指定的Span<T>通用介面搜尋整個排序的IComparable<T>值。

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

求出與 之間共用spanother的任意前綴長度。

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

求出與 之間共用spanother的任意前綴長度。

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

表示是否在一個區間內找到指定值。

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

搜尋任何指定 values 事件的發生,若找到則回傳 true 。 若未找到,則返回 false

ContainsAny<T>(Span<T>, SearchValues<T>)

搜尋任何指定 values 事件的發生,若找到則回傳 true 。 若未找到,則返回 false

ContainsAny<T>(Span<T>, T, T, T)

搜尋 、 value0value1 在指定區間內的value2出現。

ContainsAny<T>(Span<T>, T, T)

搜尋 或 的出現value0,若找到則返回value1true 若未找到,則返回 false

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

在指定區間搜尋除指定 values值外的任何值。

ContainsAnyExcept<T>(Span<T>, SearchValues<T>)

在指定區間搜尋除指定 values值外的任何值。

ContainsAnyExcept<T>(Span<T>, T, T, T)

搜尋除 value0value1、 或 value2以外的任何值。

ContainsAnyExcept<T>(Span<T>, T, T)

在指定區間搜尋除 value0value1以外的任何值。

ContainsAnyExcept<T>(Span<T>, T)

在指定區間搜尋除指定 value值外的任何值。

ContainsAnyExceptInRange<T>(Span<T>, T, T)

搜尋介於 lowInclusivehighInclusive之間的任何值,包含。

ContainsAnyInRange<T>(Span<T>, T, T)

搜尋介於 lowInclusivehighInclusive之間的任意值,包含,若找到則回傳 true 。 若未找到,則返回 false

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

計算該現象 value 在 中 span出現的次數。

Count<T>(Span<T>, T)

計算該現象 value 在 中 span出現的次數。

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

判斷指定的序列是否出現在一個區間的末端。

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

搜尋指定的序列並回傳其首次出現的索引。

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

搜尋指定值並回傳其首次出現的索引。

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

搜尋任一指定值的第一個索引。

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

搜尋任一指定值的第一個索引。

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

搜尋任一指定值的第一個索引。

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

搜尋任一指定值的第一個索引。

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

搜尋除指定 values值外的任何第一個索引。

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

搜尋除指定 values值外的任何第一個索引。

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

搜尋除 、 value0、 或 value1以外的任何值value2的第一個索引。

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

搜尋除指定兩個值外的任何值的第一個索引。

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

搜尋除指定 value值外的任何第一個索引。

IndexOfAnyExceptInRange<T>(Span<T>, T, T)

搜尋介於 lowInclusivehighInclusive之間範圍外的任何值的第一個索引,包含 。

IndexOfAnyInRange<T>(Span<T>, T, T)

搜尋介於 lowInclusivehighInclusive之間的任意值的第一個索引,包含 。

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

搜尋指定的序列並回傳其最後出現的索引。

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

搜尋指定的值,並回傳其最後出現的索引。

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

搜尋任一指定值的最後一個索引。

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

搜尋任一指定值的最後一個索引。

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

搜尋任一指定值的最後一個索引。

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

搜尋任一指定值的最後一個索引。

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

搜尋除指定 values值外的任何最後索引。

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

搜尋除指定 values值外的任何最後索引。

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

搜尋除指定 value0value1、 或 value2以外的任何值的最後索引。

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

搜尋除指定 value0 值外 value1的任何最後索引。

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

搜尋除指定 value值外的任何最後索引。

LastIndexOfAnyExceptInRange<T>(Span<T>, T, T)

搜尋任何超出 lowInclusivehighInclusive之間範圍的最後索引。

LastIndexOfAnyInRange<T>(Span<T>, T, T)

搜尋介於 lowInclusivehighInclusive之間的任意值的最後一個索引,包含 。

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

判斷區間與唯讀區間是否在記憶體中重疊,並輸出元素偏移量。

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

判斷一個區間與唯讀區間在記憶體中是否重疊。

Replace<T>(Span<T>, T, T, IEqualityComparer<T>)

將所有出現的 oldValue 取代為 newValue

Replace<T>(Span<T>, T, T)

將所有出現的 oldValue 取代為 newValue

ReplaceAny<T>(Span<T>, SearchValues<T>, T)

在所有出現的span元素中替換valuesnewValue

ReplaceAnyExcept<T>(Span<T>, SearchValues<T>, T)

將除 中元素span外的所有元素替換valuesnewValue

Reverse<T>(Span<T>)

將整個跨度中元素的順序顛倒。

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

透過使用 IComparable{T} 比較元素,決定張成與唯讀張成的相對順序。CompareTo(T)。

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

透過比較 IEqualityComparer<T>元素來判斷兩個序列是否相等。

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

透過使用 IEquatable{T} 比較元素,判斷一個跨度與唯讀個跨是否相等。等於(T)。

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

Span<T>利用 TComparer.

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

使用指定的 Span<T>來排序整個Comparison<T>元素。

Sort<T>(Span<T>)

利用 Span<T> 中每個元素IComparable<T>的實作來排序整個Span<T>元素。

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

根據第一個區域的 Span<T> 鍵,使用指定的比較器排序一對跨度(一個包含鍵,另一個包含對應項目)。

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

根據第一個鍵,使用指定的比較,排序一對跨度(一個包含鍵,另一個包含對應項目 Span<T> )。

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

根據第一個Span<T>IComparable<T>區域的鍵數,利用每個鍵的實作,排序一對跨度(一個包含鍵值,另一個包含相應項目)。

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

判斷指定序列是否出現在區間起始。

ToImmutableArray<T>(Span<T>)

將 span 轉換成不變陣列。

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

從只讀區間中移除所有指定元素的前置與後置出現。

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

移除該跨上指定元素的所有前導與後置出現。

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

從只讀區間中移除所有指定元素集合的尾隨出現。

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

移除該跨上指定元素的所有後置出現。

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

將該只讀區間中指定元素集合的所有前置出現從該區間移除。

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

移除該跨上指定元素的所有前置出現。

適用於

另請參閱