Span<T> Span<T> Span<T> Span<T> Struct

定义

提供任意内存的连续区域的类型和内存安全表示。Provides a type- and memory-safe representation of a contiguous region of arbitrary memory.

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

类型参数

T

中的项的类型Span<T>The type of items in the Span<T>.

继承

注解

Span<T>ref 结构堆栈,而不是托管堆上分配。Span<T> is a ref struct that is allocated on the stack rather than on the managed heap. Ref 结构类型有多种限制,以确保它们不能至托管堆,包括不能装箱,它们不能分配给类型的变量提升Objectdynamic为任何接口类型,也不能是中的字段引用类型,并且它们不能使用跨awaityield边界。Ref struct types have a number of restrictions to ensure that they cannot be promoted to the managed heap, including that they can't be boxed, they can't be assigned to variables of type Object, dynamic or to any interface type, they can't be fields in a reference type, and they can't be used across await and yield boundaries. 此外,对两个方法调用Equals(Object)GetHashCode,引发NotSupportedExceptionIn addition, calls to two methods, Equals(Object) and GetHashCode, throw a NotSupportedException.

重要

它是仅限堆栈的类型,因为Span<T>不合适,则需要将对缓冲区的引用存储在堆上的很多情况下。Because it is a stack-only type, Span<T> is unsuitable for many scenarios that require storing references to buffers on the heap. 这是如此,例如,进行异步方法调用的例程。This is true, for example, of routines that make asynchronous method calls. 对于这种情况下,可以使用补充System.Memory<T>System.ReadOnlyMemory<T>类型。For such scenarios, you can use the complementary System.Memory<T> and System.ReadOnlyMemory<T> types.

表示不可变的或只读结构的范围,对于使用System.ReadOnlySpan<T>For spans that represent immutable or read-only structures, use System.ReadOnlySpan<T>.

跨度<T > 和内存Span<T> and memory

一个Span<T>表示任意内存的相邻区域。A Span<T> represents a contiguous region of arbitrary memory. 一个Span<T>实例通常用来保存数组的元素或数组的一部分。A Span<T> instance is often used to hold the elements of an array or a portion of an array. 一个数组,但是,与Span<T>实例可以指向托管内存,本机内存,或上管理的内存堆栈。Unlike an array, however, a Span<T> instance can point to managed memory, native memory, or memory managed on the stack. 下面的示例创建Span<Byte>从数组:The following example creates a Span<Byte> from an array:

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

下面的示例创建Span<Byte>从 100 个字节的本机内存:The following example creates a Span<Byte> from 100 bytes of native memory:

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

下面的示例使用C# stackalloc关键字来分配 100 个字节的堆栈上的内存:The following example uses the C# stackalloc keyword to allocate 100 bytes of memory on the stack:

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

因为Span<T>通过任意内存块,方法是一种抽象Span<T>类和方法与Span<T>参数对任何Span<T>而不考虑其要封装的内存的类型的对象。Because Span<T> is an abstraction over an arbitrary block of memory, methods of the Span<T> class and methods with Span<T> parameters operate on any Span<T> object regardless of the kind of memory it encapsulates. 例如,每个单独的代码部分进行初始化的跨度和计算其元素的总和可以更改到的单一初始化和计算方法,如下面的示例演示了:For example, each of the separate sections of code that initialize the span and calculate the sum of its elements can be changed into single initialization and calculation methods, as the following example illustrates:

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

跨度<T > 和数组Span<T> and arrays

时它将数组中,包装Span<T>像在中的示例中,可以包装整个数组跨度<T > 和内存部分。When it wraps an array, Span<T> can wrap an entire array, as it did in the examples in the Span<T> and memory section. 因为它支持切片Span<T>也可以指向任何连续范围的数组中。Because it supports slicing, Span<T> can also point to any contiguous range within the array.

以下示例创建的 10 元素整数数组中间的五个元素的切片。The following example creates a slice of the middle five elements of a 10-element integer array. 请注意代码加倍的切片中的每个整数的值。Note that the code doubles the values of each integer in the slice. 如输出所示,跨度所做的更改会反映在数组的值。As the output shows, the changes made by the span are reflected in the values of the array.

using System;

namespace span
{
    class Program
    {
        static void Main(string[] args)
        {
            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

跨度<T > 和切片Span<T> and slices

Span<T> 包括的两个重载Slice超出当前指定的索引位置开始的范围形成一个切片的方法。Span<T> includes two overloads of the Slice method that form a slice out of the current span that starts at a specified index. 这样就可以将处理中的数据Span<T>为一系列可以根据需要通过数据处理管道,其中包含最小性能影响的部分处理的逻辑块。This makes it possible to treat the data in a Span<T> as a set of logical chunks that can be processed as needed by portions of a data processing pipeline with minimal performance impact. 例如,由于基于文本的通常是新式服务器协议,字符串和子字符串的操作是尤为重要。For example, since modern server protocols are often text-based, manipulation of strings and substrings is particularly important. 在中String类,主要方法提取子字符串是SubstringIn the String class, the major method for extracting substrings is Substring. 对于依赖于广泛的字符串操作的数据管道,其使用提供一些性能损失,因为它:For data pipelines that rely on extensive string manipulation, its use offers some performance penalties, since it:

  1. 创建一个新的字符串来保存子字符串。Creates a new string to hold the substring.

  2. 将字符的子集从原始字符串复制到新的字符串。Copies a subset of the characters from the original string to the new string.

此分配和复制操作可通过使用消除Span<T>ReadOnlySpan<T>,如下面的示例所示:This allocation and copy operation can be eliminated by using either Span<T> or ReadOnlySpan<T>, as the following example shows:

using System;

class Program
{
    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

构造函数

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

在整个指定数组上创建新的 Span<T> 对象。Creates a new Span<T> object over the entirety of a specified array.

Span<T>(Void*, Int32) Span<T>(Void*, Int32) Span<T>(Void*, Int32) Span<T>(Void*, Int32)

从指定的内存地址开始,从指定 T 元素数创建新的 Span<T> 对象。Creates a new Span<T> object from a specified number of T elements starting at a specified memory address.

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

从指定索引开始,创建包含数组的指定元素数的新 Span<T> 对象。Creates a new Span<T> object that includes a specified number of elements of an array starting at a specified index.

属性

Empty Empty Empty Empty

返回空的 Span<T> 对象。Returns an empty Span<T> object.

IsEmpty IsEmpty IsEmpty IsEmpty

返回一个值,该值指示当前的 Span<T> 是否为空。Returns a value that indicates whether the current Span<T> is empty.

Item[Range] Item[Range] Item[Range] Item[Range]
Item[Int32] Item[Int32] Item[Int32] Item[Int32]

获取指定基于零的索引处的元素。Gets the element at the specified zero-based index.

Item[Index] Item[Index] Item[Index] Item[Index]
Length Length Length Length

返回当前范围的长度。Returns the length of the current span.

方法

Clear() Clear() Clear() Clear()

清除此 Span<T> 对象的内容。Clears the contents of this Span<T> object.

CopyTo(Span<T>) CopyTo(Span<T>) CopyTo(Span<T>) CopyTo(Span<T>)

将此 Span<T> 的内容复制到目标 Span<T>Copies the contents of this Span<T> into a destination Span<T>.

Equals(Object) Equals(Object) Equals(Object) Equals(Object)

不支持对此方法的调用。Calls to this method are not supported.

Fill(T) Fill(T) Fill(T) Fill(T)

用指定的值填充此范围的元素。Fills the elements of this span with a specified value.

GetEnumerator() GetEnumerator() GetEnumerator() GetEnumerator()

返回用于此 Span<T> 的枚举器。Returns an enumerator for this Span<T>.

GetHashCode() GetHashCode() GetHashCode() GetHashCode()

引发 NotSupportedExceptionThrows a NotSupportedException.

GetPinnableReference() GetPinnableReference() GetPinnableReference() GetPinnableReference()

返回对索引为零处 Span<T> 元素的引用。Returns a reference to the element of the Span<T> at index zero.

Slice(Index) Slice(Index) Slice(Index) Slice(Index)
Slice(Int32) Slice(Int32) Slice(Int32) Slice(Int32)

从指定索引处开始的当前范围外形成切片。Forms a slice out of the current span that begins at a specified index.

Slice(Range) Slice(Range) Slice(Range) Slice(Range)
Slice(Int32, Int32) Slice(Int32, Int32) Slice(Int32, Int32) Slice(Int32, Int32)

从指定长度的指定索引处开始,在当前范围外形成切片。Forms a slice out of the current span starting at a specified index for a specified length.

ToArray() ToArray() ToArray() ToArray()

将此范围的内容复制到新数组中。Copies the contents of this span into a new array.

ToString() ToString() ToString() ToString()

返回此 Span<T> 对象的字符串表示形式。Returns the string representation of this Span<T> object.

TryCopyTo(Span<T>) TryCopyTo(Span<T>) TryCopyTo(Span<T>) TryCopyTo(Span<T>)

尝试将当前 Span<T> 复制到目标 Span<T>,并返回一个指示复制操作是否成功的值。Attempts to copy the current Span<T> to a destination Span<T> and returns a value that indicates whether the copy operation succeeded.

操作员

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

返回一个值,该值指示两个 Span<T> 对象是否相等。Returns a value that indicates whether two Span<T> objects are equal.

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

定义 ArraySegment<T>Span<T> 的隐式转换。Defines an implicit conversion of an ArraySegment<T> to a Span<T>.

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

定义 Span<T>ReadOnlySpan<T> 的隐式转换。Defines an implicit conversion of a Span<T> to a ReadOnlySpan<T>.

Implicit(T[] to Span<T>) Implicit(T[] to Span<T>) Implicit(T[] to Span<T>) Implicit(T[] to Span<T>)

定义数组到 Span<T> 的隐式转换。Defines an implicit conversion of an array to a Span<T>.

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

返回一个值,该值指示两个 Span<T> 对象是否不相等。Returns a value that indicates whether two Span<T> objects are not equal.

扩展方法

BinarySearch<T>(Span<T>, IComparable<T>) BinarySearch<T>(Span<T>, IComparable<T>) BinarySearch<T>(Span<T>, IComparable<T>) BinarySearch<T>(Span<T>, IComparable<T>)
BinarySearch<T,TComparer>(Span<T>, T, TComparer) BinarySearch<T,TComparer>(Span<T>, T, TComparer) BinarySearch<T,TComparer>(Span<T>, T, TComparer) BinarySearch<T,TComparer>(Span<T>, T, TComparer)
BinarySearch<T,TComparable>(Span<T>, TComparable) BinarySearch<T,TComparable>(Span<T>, TComparable) BinarySearch<T,TComparable>(Span<T>, TComparable) BinarySearch<T,TComparable>(Span<T>, TComparable)
EndsWith<T>(Span<T>, ReadOnlySpan<T>) EndsWith<T>(Span<T>, ReadOnlySpan<T>) EndsWith<T>(Span<T>, ReadOnlySpan<T>) EndsWith<T>(Span<T>, ReadOnlySpan<T>)
IndexOf<T>(Span<T>, T) IndexOf<T>(Span<T>, T) IndexOf<T>(Span<T>, T) IndexOf<T>(Span<T>, T)
IndexOf<T>(Span<T>, ReadOnlySpan<T>) IndexOf<T>(Span<T>, ReadOnlySpan<T>) IndexOf<T>(Span<T>, ReadOnlySpan<T>) IndexOf<T>(Span<T>, ReadOnlySpan<T>)
IndexOfAny<T>(Span<T>, T, T) IndexOfAny<T>(Span<T>, T, T) IndexOfAny<T>(Span<T>, T, T) IndexOfAny<T>(Span<T>, T, T)
IndexOfAny<T>(Span<T>, T, T, T) IndexOfAny<T>(Span<T>, T, T, T) IndexOfAny<T>(Span<T>, T, T, T) IndexOfAny<T>(Span<T>, T, T, T)
IndexOfAny<T>(Span<T>, ReadOnlySpan<T>) IndexOfAny<T>(Span<T>, ReadOnlySpan<T>) IndexOfAny<T>(Span<T>, ReadOnlySpan<T>) IndexOfAny<T>(Span<T>, ReadOnlySpan<T>)
LastIndexOf<T>(Span<T>, T) LastIndexOf<T>(Span<T>, T) LastIndexOf<T>(Span<T>, T) LastIndexOf<T>(Span<T>, T)
LastIndexOf<T>(Span<T>, ReadOnlySpan<T>) LastIndexOf<T>(Span<T>, ReadOnlySpan<T>) LastIndexOf<T>(Span<T>, ReadOnlySpan<T>) LastIndexOf<T>(Span<T>, ReadOnlySpan<T>)
LastIndexOfAny<T>(Span<T>, T, T) LastIndexOfAny<T>(Span<T>, T, T) LastIndexOfAny<T>(Span<T>, T, T) LastIndexOfAny<T>(Span<T>, T, T)
LastIndexOfAny<T>(Span<T>, T, T, T) LastIndexOfAny<T>(Span<T>, T, T, T) LastIndexOfAny<T>(Span<T>, T, T, T) LastIndexOfAny<T>(Span<T>, T, T, T)
LastIndexOfAny<T>(Span<T>, ReadOnlySpan<T>) LastIndexOfAny<T>(Span<T>, ReadOnlySpan<T>) LastIndexOfAny<T>(Span<T>, ReadOnlySpan<T>) LastIndexOfAny<T>(Span<T>, ReadOnlySpan<T>)
Overlaps<T>(Span<T>, ReadOnlySpan<T>) Overlaps<T>(Span<T>, ReadOnlySpan<T>) Overlaps<T>(Span<T>, ReadOnlySpan<T>) Overlaps<T>(Span<T>, ReadOnlySpan<T>)
Overlaps<T>(Span<T>, ReadOnlySpan<T>, Int32) Overlaps<T>(Span<T>, ReadOnlySpan<T>, Int32) Overlaps<T>(Span<T>, ReadOnlySpan<T>, Int32) Overlaps<T>(Span<T>, ReadOnlySpan<T>, Int32)
Reverse<T>(Span<T>) Reverse<T>(Span<T>) Reverse<T>(Span<T>) Reverse<T>(Span<T>)
SequenceCompareTo<T>(Span<T>, ReadOnlySpan<T>) SequenceCompareTo<T>(Span<T>, ReadOnlySpan<T>) SequenceCompareTo<T>(Span<T>, ReadOnlySpan<T>) SequenceCompareTo<T>(Span<T>, ReadOnlySpan<T>)
SequenceEqual<T>(Span<T>, ReadOnlySpan<T>) SequenceEqual<T>(Span<T>, ReadOnlySpan<T>) SequenceEqual<T>(Span<T>, ReadOnlySpan<T>) SequenceEqual<T>(Span<T>, ReadOnlySpan<T>)
StartsWith<T>(Span<T>, ReadOnlySpan<T>) StartsWith<T>(Span<T>, ReadOnlySpan<T>) StartsWith<T>(Span<T>, ReadOnlySpan<T>) StartsWith<T>(Span<T>, ReadOnlySpan<T>)

适用于