博客 / 詳情

返回

C# 的 ReadOnlySpan

提供任意內存的連續區域的類型安全且內存安全的只讀(ReadOnly)表示形式。

[ System . Runtime . InteropServices . Marshalling . NativeMarshalling ( typeof ( System . Runtime . InteropServices . Marshalling . ReadOnlySpanMarshaller < , > ) ) ]
public readonly ref struct ReadOnlySpan<T>

類型參數

參數 註解
T ReadOnlySpan 中項的類型

繼承

Object ValueType ReadOnlySpan < T >

特性

NativeMarshallingAttribute

註解

ReadOnlySpan < T > 類型是一種 ref struct,它在棧上分配,而非託管堆上。ref struct 類型有諸多限制,以確保它們不會被提升到託管堆,其中包括:它們不能被裝箱,不能賦值給 Object 類型、dynamic 類型的變量或任何接口類型的變量,不能作為引用類型中的字段,也不能跨 await 和 yield 邊界使用。此外,調用 Equals ( Object ) 和 GetHashCode 這兩個方法會拋出 NotSupportedException。

ReadOnlySpan < T > 實例通常用於存儲數組的元素或數組的一部分。不過,與數組不同的是,ReadOnlySpan < T > 實例可以指向託管內存、本機內存或堆棧上管理的內存。

構造函數

重載

重載 註解
ReadOnlySpan < T > ( T ) 圍繞指定的引用創建一個長度為 1 的新 ReadOnlySpan < T >
ReadOnlySpan < T > ( T [ ] ) 在指定數組的整個範圍內創建一個新 ReadOnlySpan < T >
ReadOnlySpan < T > ( T [ ] , Int32 索引 , Int32 元素數 ) 在指定數組的整個範圍內創建一個新 ReadOnlySpan < T >
Span < T > ( void* 指針 , Int32 元素數 ) 從指定的內存地址開始,從指定數量的 T 元素創建一個新的Span < T > 對象
public ReadOnlySpan ( ref readonly T 引用 );
public ReadOnlySpan ( T [ ]? 數組 );
public Span ( T [ ]? 數組 , int 起始索引 , int 元素數 );
[ System . CLSCompliant ( false ) ]
public Span ( void* 指針 , int 長度 );

參數

參數 類型 註解
引用 T 任意類型的單個值(傳遞的是對其的引用),單個值的 ReadonlySpan
數組 T [ ]? 任意類型的數組,對其元素引用的 Span
起始索引
元素數
int 當 Span 的元素只是引用 數組 中的一部分時,指定起始索引和元素數(省略元素數將引用 起始索引 後的所有元素)
指針 void* 指向內存中指定數量的 T 元素起始地址的指針
長度 int 要包含在 Span < T > 中的 T 元素數量

異常

異常 註解
ArrayTypeMismatchException T 是引用類型,但 數組 不是 T 類型的數組
ArgumentException 若指定 指針 和 長度,T 是引用類型或包含指針,因此無法存儲在非託管內存中
ArgumentOutOfRangeException 若指定 指針 和 長度,但長度小於 0
若指定 起始索引 和 元素數,起始索引 + 元素數 > 數組 . Length
或 起始索引 > 數組 . Length
或 數組 為 null,但 起始索引 和/或 元素數 不是 0

示例

以下示例演示了 ReadOnlySpan 構造函數的基礎示例:

int ZHS = 1;
ReadOnlySpan < int > ZHSSpan = new ( ref ZHS );
foreach ( var z in ZHSSpan )
    Console . WriteLine ( z );

int [ ] ZHSs = [ 2 , 3 , 4 ];
ReadOnlySpan < int > ZHSsSpan = new ( ZHSs );
foreach ( var z in ZHSsSpan )
    Console . WriteLine ( z );

ReadOnlySpan < int > ZHSsBFSpan = new ( ZHSs , 1 , 2 );
foreach ( var z in ZHSsBFSpan )
    Console . WriteLine ( z );

屬性

Empty 和 IsEmpty

Empty 返回一個空的(不是 null)ReadOnlySpan < T > 對象;IsEmpty 返回指定 ReadOnlySpan 對象是否為 Empty。

public static ReadOnlySpan < T > Empty { get; }
public bool IsEmpty { get; }

屬性值

方法 屬性值 註解
Empty ReadonlySpan < T > 一個沒有元素的 Span < T > 對象
IsEmpty bool 如果 實例 是沒有元素的(不是 null ),返回 true;否則返回 false

示例

int [ ] ZHSs = [ 1 , 2 ];
int [ ]? ZHSnull = null;

ReadOnlySpan < int > zhsReadOnlySpan = new ( ZHSs );
bool Berkong = zhsReadOnlySpan . IsEmpty;
foreach ( var z in zhsReadOnlySpan )
    Console . Write ( $"{z}    " ); Console . WriteLine ( $"{( Berkong ? "是" : "不是" )}空的" );

Console . WriteLine ( );
Console . WriteLine ( "下面將 ReadOnlySpan 置空:" );
zhsReadOnlySpan = [ ]; // .NET 推薦簡化形式,其實就是 ReadOnlySpan < int > . Empty
Berkong = zhsReadOnlySpan . IsEmpty;
Console . WriteLine ( $"{zhsReadOnlySpan . ToString ( )} {( Berkong ? "是" : "不是" )}空的" );

Console . WriteLine ( "下面是以 null 數組創建的 ReadOnlySpan:" );
ReadOnlySpan < int > ReadOnlySpannull = new ( ZHSnull );
Berkong = ReadOnlySpannull . IsEmpty;
Console . WriteLine ( $"{ReadOnlySpannull . ToString ( )} {( Berkong ? "是" : "不是" )}空的" );

註解

自 null 數組和 Empty 數組創建的 ReadOnlySpan 均為 0 元素 Span。

ReadOnlySpan . Item [ ] 和 ReadOnlySpan . Length

Item [ 索引 ] 返回 ReadOnlySpan 中指定索引處的元素(引用);Length 返回 ReadOnlySpan 的元素數(長度)。

public ref T this [ int 索引 ] { get; }
public int Length { get; }

屬性值

方法 類型 註解
Item T 位於指定索引處的元素值(引用)
Length Int32 ReadOnlySpan 實例的長度

異常

異常 註解
IndexOutOfRangeException 索引 > 實例 . Length
索引 < 0

示例

int [ ] ZHSs = [ 1 , 2 ];
int [ ]? ZHSnull = null;

ReadOnlySpan < int > zhsReadOnlySpan = new ( ZHSs );
Console . WriteLine ( $"自有元素的數組創建的 ReadOnlySpan 的長度:{zhsReadOnlySpan . Length}" );
for ( int z = 0 ; z < zhsReadOnlySpan . Length ; z++ )
    Console . WriteLine ( zhsReadOnlySpan [ z ] );

// 置空 ReadOnlySpan
zhsReadOnlySpan = [ ];
Console . WriteLine ( $"數組創建的 ReadOnlySpan 被 Empty 之後的長度:{zhsReadOnlySpan . Length}" );
for ( int z = 0 ; z < zhsReadOnlySpan . Length ; z++ )
    Console . WriteLine ( zhsReadOnlySpan [ z ] );

zhsReadOnlySpan = new ( ZHSnull );
Console . WriteLine ( $"空數組創建的 ReadOnlySpan 的長度:{zhsReadOnlySpan . Length}" );
for ( int z = 0 ; z < zhsReadOnlySpan . Length ; z++ )
    Console . WriteLine ( zhsReadOnlySpan [ z ] );

方法

ReadOnlySpan . CastUp

將 T派生 的只讀範圍轉換為 T基 的只讀範圍。
public static ReadOnlySpan < T > CastUp < T派生 > ( ReadOnlySpan < T派生 > 項目s ) where T派生 : class, T基;

參數

參數 類型 註解
T派生 欲轉換的類型(必須為 T基 的派生類型)
項目s T派生 源只讀範圍,不進行復制
T基 T派生 的基類型

返回值

類型 註解
ReadOnlySpan < T基 > 將 項目s 中的 T派生 轉換為 T基 的只讀範圍

示例

ReadOnlySpan < LEI派生 > PSs = [ new LEI派生 ( ) , new LEI派生 ( ) ];
// 由於 FF空方法 的參數是 ReadOnlySpan < LEI基 >,需要對 PSs 轉換
ReadOnlySpan < LEI基 > JIs = ReadOnlySpan < LEI基 > . CastUp ( PSs );
FF空方法 ( JIs );

static void FF空方法 ( ReadOnlySpan < LEI基 > 基礎類 )
    {
    Console . WriteLine ( 基礎類 . ToString ( ) );
    }

public class LEI基
    {

    }

public class LEI派生 : LEI基
    {

    }

備註

此方法使用協變強制轉換,生成與源共享相同內存的只讀範圍。類型約束中表達的關係確保了該強制轉換是一種安全操作。

Span . CopyTo

將此 Span < T > 的內容複製到目標 Span < T > 中。
public void CopyTo ( Span < T > 目標 );

參數

參數 類型 註解
目標 Span < T > 欲複製的目標 Span

異常

異常 註解
ArgumentException 目標 比 實例 短

示例

下面這個例程複製了一個 ReadOnlySpan:

int [ ] ZHSs = [ 1 , 2 , 3 ];
ReadOnlySpan < int > ZHSsReadOnlySpan = new ( ZHSs );

Span < int > ZHSsReadOnlySpan複製 = stackalloc int [ ZHSsReadOnlySpan . Length ];
ZHSsReadOnlySpan . CopyTo ( ZHSsReadOnlySpan複製 );

Console . WriteLine ( $"源 ReadOnlySpan:" );
foreach ( var z in ZHSsReadOnlySpan )
    Console . Write ( $"{z}    " );

Console . WriteLine ( );
Console . WriteLine ( $"目標 Span:" );
foreach ( var z in ZHSsReadOnlySpan複製 )
    Console . Write ( $"{z}    " );

備註

如果 實例 和 目標 重疊,實例 的全部內容會先被複制到臨時位置,再從臨時位置複製到 目標。

與 Span . CopyTo 不同,Span 的複製行為可能導致數據複製前被覆蓋。

ReadOnlySpan . Equals 和 ReadOnlySpan . GetHashCode

Equals 是比較兩個 ReadOnlySpan 是否相等的方法;GetHashCode 方法返回 實例 的哈希代碼。均不支持。

[ System . Obsolete ( "Equals ( ) on Span will always throw an exception. Use the equality operator instead." ) ]
public override bool Equals ( object? 對象 );

[ System . Obsolete ( "GetHashCode ( ) on Span will always throw an exception." ) ]
public override int GetHashCode ( );

參數

| 參數 | 類型 | 註解 |
| 對象 | object? | 不支持 |

返回值

| 方法 | 類型 | 註解 |
| Equals | bool | 不支持
| GetHashCode | Int32 |不支持 |

異常

| 異常 | 註解 |
| NotSupportedException | 總是不支持這兩個方法 |

Span . GetEnumerator

返回此 ReadOnlySpan < T > 的枚舉器。
public ReadOnlySpan < T > . Enumerator GetEnumerator ( );

參數

參數 類型 註解
T 任意類型 返回值中的枚舉器的類型

返回值

類型 註解
ReadOnlySpan < T > . Enumerator 此 實例 的枚舉器

備註

無需直接調用 GetEnumerator 方法,您可以使用 C# 的 foreach 語句以及 Visual Basic 的 For Each … Next 結構來枚舉 ReadOnlySpan < T >。
ReadOnlySpan . Slice
從當前只讀範圍中切分出一個切片,該切片從指定索引開始,可以具有指定長度。

重載

重載 註解
Slice ( int 起始索引 ) 自當前只讀範圍 實例 的指定索引處起始的切片Slice
( int 起始索引 , int 元素數 ) 自當前只讀範圍 實例 的指定索引處起始的切片,具有 元素數 長度
public Span < T > Slice ( int 起始索引 );
public Span < T > Slice ( int 起始索引 , int 元素數 );

參數

參數 類型 註解
起始索引
元素數
int 指定切片的起始索引,若不指定 元素數,則切片至 ReadOnlySpan 的末尾

返回值

類型 註解
ReadOnlySpan < T > 按照指定範圍切片 實例 後的 ReadOnlySpan

異常

| 異常 | 註解 |
| ArgumentOutOfRangeException | 起始索引 和/或 元素數 < 0
起始索引(或 + 元素數)> 實例 . Length |

示例

int [ ] ZHSs = [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 ];

ReadOnlySpan < int > ZHSsReadOnlySpan = ZHSs . AsSpan ( );

ReadOnlySpan < int > ReadOnlySpan3 = ZHSsReadOnlySpan [  3 .. ]; // .NET 推薦使用範圍運算符,實際為 ZHSsReadOnlySpan . Slice ( 3 )
ReadOnlySpan < int > ReadOnlySpan07 = ZHSsReadOnlySpan [ .. 7 ];
ReadOnlySpan < int > ReadOnlySpan25 = ZHSsReadOnlySpan . Slice ( 2 , 5 );

Console . WriteLine ( "ReadOnlySpan3 的元素:" );
Console . WriteLine ( string . Join ( ',' , ReadOnlySpan3 . ToArray ( ) ) );

Console . WriteLine ( "ReadOnlySpan25 的元素:" );
Console . WriteLine ( string . Join ( ',' , ReadOnlySpan25 . ToArray ( ) ) );

Console . WriteLine ( "ReadOnlySpan07 的元素:" );
Console . WriteLine ( string . Join ( ',' , ReadOnlySpan07 . ToArray ( ) ) );

註解

起始索引 從 0 起始。

新版的 .NET 推薦使用範圍運算符替換沒有 元素數 參數或 起始索引 參數為 0 的 Slice(但不推薦替換使用元素數的 Slice,或許 Slice 更易讀):

  • ReadOnlySpan [ 3 .. ] == ReadOnlySpan . Slice ( 3 )
  • ReadOnlySpan [ .. 7 ] == ReadOnlySpan . Slice ( 0 , 7 )
  • ReadOnlySpan [ 2 .. 4 ] == ReadOnlySpan . Slice ( 2 , 2 ) // 不被推薦的替換

Slice 允許返回 Empty ReadOnlySpan,即 起始索引(無 元素數 參數) == 實例 . Length 或 元素數 == 0。

Span . ToArray

將此只讀範圍的內容複製到新數組中。
public T [ ] ToArray ( );

返回值

| 類型 | 註解 |
| T [ ] | 與 Span 實例 相同類型的數組,包含 實例 中的所有元素 |

示例

以下示例展示了 ToArray 方法的實用範圍之一,即 ReadonlySpan 的排序,ReadOnlySpan 沒有 Sort 方法,因為它是隻讀的。可借用 ToArray 方法,對其返回的數組排序,再覆蓋原 ReadOnlySpan,得到已排序的 ReadOnlySpan:

int [ ] ZHSs = [ 10 , 32 , 23 , 74 , 56 , 65 , 7 , 38 ];

ReadOnlySpan < int > ZHSsReadOnlySpan = ZHSs . AsSpan ( );

// 僅處理 ReadOnlySpan,排序它
ZHSs = ZHSsReadOnlySpan . ToArray ( );
Array . Sort ( ZHSs );
ZHSsReadOnlySpan = ZHSs . AsSpan ( );
foreach ( var z in ZHSsReadOnlySpan )
    Console . Write ( $"{z}    " );
Console . WriteLine ( );

備註

此方法會執行堆分配,因此應儘可能避免使用。在處理數組的 API 中,堆分配是常見的。如果不存在接受 ReadOnlySpan < T > 的替代 API 重載,那麼使用此類 API 就無法避免。

ReadOnlySpan . ToString

返回此 ReadOnlySpan < T > 對象的字符串表示形式。
public override string ToString ( );

返回值

類型 註解
String Span 實例 的字符串表示形式

示例

請注意 ReadOnlySpan < char > 與其他 ReadOnlySpan 的區別:

int [ ] ZHSs = [ 10 , 32 , 23 , 74 , 56 , 65 , 7 , 38 ];
ReadOnlySpan < int > ZHSsReadOnlySpan = ZHSs . AsSpan ( );

char [ ] ZFs = [ 'a' , 'b' , 'c' ];
ReadOnlySpan < char > ZFsReadOnlySpan = ZFs . AsSpan ( );

string [ ] ZFCs = [ "龍生" , "九子" , "皆非龍" ];
ReadOnlySpan < string > ZFCsReadOnlySpan = ZFCs . AsSpan ( );

Console . WriteLine ( $"ZFsReadOnlySpan . ToString ( ) = {ZFsReadOnlySpan}" );
Console . WriteLine ( $"ZFCsReadOnlySpan . ToString ( ) = {ZFCsReadOnlySpan . ToString ( )}" );
Console . WriteLine ( $"ZHSsReadOnlySpan . ToString ( ) = {ZHSsReadOnlySpan . ToString ( )}" );

備註

對於 ReadOnlySpan < Char >,ToString 方法會返回一個 String,其中包含 ReadOnlySpan < T > 所指向的字符。否則,它會返回一個 String,其中包含該類型的名稱以及 ReadOnlySpan < T > 所包含的元素數量,類似下列格式:
System . Span < 元素類型 > [ 元素數 ]

Span . TryCopyTo

嘗試將當前的 ReadOnlySpan < T > 實例複製到目標 Span < T >,並返回一個指示覆制操作是否成功的值。
public bool TryCopyTo ( Span < T > 目標 );

參數

類型 註解
Span < T > 欲將 實例 複製到的目標 Span

返回值

類型 註解
bool 如果複製成功,返回 true,否則返回 false

示例

bool BerCopy;
int [ ] ZHSs源 = [ 10 , 32 , 23 ] , ZHSs目標 = [ 2 , 8 , 10 ];
ReadOnlySpan < int > ZHSsReadOnlySpan源 = ZHSs源 . AsSpan ( );

Span < int > ZHSsSpan目標 = ZHSs目標 . AsSpan ( );
foreach ( var z in ZHSsSpan目標 )
    Console . Write ( $"{z}    " );
Console . WriteLine ( );

BerCopy = ZHSsReadOnlySpan源 . TryCopyTo ( ZHSsSpan目標 );
if ( BerCopy )
    {
    foreach ( var z in ZHSsSpan目標 )
        Console . Write ( $"{z}    " );
    }
else Console . WriteLine ( "複製不成功!" );

Console . WriteLine ( );
int [ ] ZHS4 = [ 4 , 4 , 4 , 4 ];
ZHSsSpan目標 = ZHS4 . AsSpan ( );
foreach ( var z in ZHSsSpan目標 )
    Console . Write ( $"{z}    " );
Console . WriteLine ( );

BerCopy = ZHSsReadOnlySpan源 . TryCopyTo ( ZHSsSpan目標 );
if ( BerCopy )
    {
    foreach ( var z in ZHSsSpan目標 )
        Console . Write ( $"{z}    " );
    }
else Console . WriteLine ( "複製不成功!" );

Console . WriteLine ( );
int [ ] ZHS2 = [ 2 , 2 ];
ZHSsSpan目標 = ZHS2 . AsSpan ( );
foreach ( var z in ZHSsSpan目標 )
    Console . Write ( $"{z}    " );
Console . WriteLine ( );

BerCopy = ZHSsReadOnlySpan源 . TryCopyTo ( ZHSsSpan目標 );
if ( BerCopy )
    {
    foreach ( var z in ZHSsSpan目標 )
        Console . Write ( $"{z}    " );
    }
else Console . WriteLine ( "複製不成功!" );

備註

TryToCopy 若要返回 true,必須滿足:
實例 的 T 必須與 目標 的 T 相同(否則編譯器即不通過);
實例 的長度必須小於等於 目標 的長度,即:
實例 . Length <= 目標 . Length

如果 實例 和 目標 重疊,則整個 實例 的處理方式就如同先將其複製到臨時位置,再複製到 目標 一樣。

// 即使源和目標重疊,也能正確複製
int [ ] ZHSs = { 1 , 2 , 3 , 4 , 5 };
ReadOnlySpan < int > yuan = array . AsSpan ( 0 , 3 ); // [ 1 , 2 , 3 ]
Span < int > mubiao = array . AsSpan ( 2 , 3 ); // [ 3 , 4 , 5 ]

// 安全複製,不會出現數據損壞
yuan . TryCopyTo ( mubiao ); // ZHSs 變為:[ 1 , 2 , 1 , 2 , 3 ]

當 TryCopyTo 返回 false 時,不會向 目標 寫入任何數據。

運算符

Equality(相等性)

返回一個 bool 值,該值指示兩個 ReadOnlySpan < T > 對象是否相等。
public static bool operator == ( ReadOnlySpan < T > 左 , ReadOnlySpan < T > 右 );

參數

參數 類型 註解

ReadOnlySpan < T > 欲比較的 ReadOnlySpan 只讀範圍

返回值

類型 註解
bool 若兩個 ReadOnlySpan < T > 對象相等,返回 true;否則返回 false

示例

int [ ] array1 =  [ 1 , 2 , 3 , 4 , 5 ];
int [ ] array2 =  [ 1 , 2 , 3 , 4 , 5 ]; // 內容相同但引用不同

// 創建指向同一數組的 ReadOnlySpan
ReadOnlySpan < int > span1 = array1 . AsSpan ( );
ReadOnlySpan < int > span2 = array1 . AsSpan ( ); // 指向同一數組

// 創建指向不同數組但內容相同的ReadOnlySpan
ReadOnlySpan<int> span3 = array2 . AsSpan ( ); // 指向不同數組但內容相同

// 創建指向同一數組不同部分的 ReadOnlySpan
ReadOnlySpan < int > span4 = array1 . AsSpan ( 0 ,  3 ); // [ 1 , 2 , 3 ]
ReadOnlySpan < int > span5 = array1 . AsSpan ( 2 , 3 ); // [ 3 , 4 , 5 ]

Console . WriteLine ( "比較結果:" );
Console . WriteLine ( $"span1 == span2:{span1 == span2}" ); // true - 同一內存
Console . WriteLine ( $"span1 == span3:{span1 == span3}" ); // false - 不同內存
Console . WriteLine ( $"span4 == span5:{span4 == span5}" ); // false - 不同內存區域

// 內容比較(需要手動實現)
bool contentsEqual = span1 . SequenceEqual ( span3 );
Console . WriteLine ( $"span1 . SequenceEqual ( span3 ):{contentsEqual}" ); // true - 內容相同

備註

兩個 ReadOnlySpan < T > 對象相等的條件是它們具有相同的長度,且 左 和 右 的對應元素指向相同的內存。請注意,相等性測試不會嘗試判斷內容是否相等。

Implicit(隱式)

定義數組到 ReadOnlySpan;數組分段(Segment)到 Span 的隱式轉換。

public static implicit operator Span < T > ( T [ ]? 數組 );
public static implicit operator Span < T > ( ArraySegment < T > 分段 );

參數

參數 類型 註解
數組 T [ ]? 欲轉換為 ReadOnlySpan < T > 的數組
分段 ArraySegment < T > 欲轉換為 ReadOnlySpan < T > 的數組分段

返回值

類型 註解
ReadOnlySpan < T > 與 數組 或其片段對應的只讀範圍

示例

int [ ] ZHSs = [ 1 , 2 , 3 ];
ReadOnlySpan < int > ZHSsSpan = ZHSs;

string zfc = "倒黴孩子!";
ReadOnlySpan < char >  ZFCsSpan = zfc;

ArraySegment < int > PD = new ( ZHSs  , 1 , 2 );
ReadOnlySpan < int > ZHSsPDSpan = PD;

foreach ( var z in ZHSsSpan )
    Console . Write ( $"{z}    " );
Console . WriteLine ( );

foreach ( var z in ZFCsSpan )
    Console . Write ( $"{z}    " );
Console . WriteLine ( );

foreach ( var z in ZHSsPDSpan )
    Console . Write ( $"{z}    " );
Console . WriteLine ( );

Inequality(不等性)

返回一個 bool 值,該值指示兩個 ReadOnlySpan < T > 對象是否不相等。
public static bool operator != ( Span < T > 左 , Span < T > 右 );

參數

參數 類型 註解

ReadOnlySpan < T > 欲比較的 ReadOnlySpan 只讀範圍

返回值

類型 註解
bool 若兩個 ReadOnlySpan < T > 對象不相等,返回 true;否則返回 false

示例

int [ ] array1 =  [ 1 , 2 , 3 , 4 , 5 ];
int [ ] array2 =  [ 1 , 2 , 3 , 4 , 5 ]; // 內容相同但引用不同

// 創建指向同一數組的 ReadOnlySpan
ReadOnlySpan < int > span1 = array1 . AsSpan ( );
ReadOnlySpan < int > span2 = array1 . AsSpan ( ); // 指向同一數組

// 創建指向不同數組但內容相同的ReadOnlySpan
ReadOnlySpan<int> span3 = array2 . AsSpan ( ); // 指向不同數組但內容相同

// 創建指向同一數組不同部分的 ReadOnlySpan
ReadOnlySpan < int > span4 = array1 . AsSpan ( 0 ,  3 ); // [ 1 , 2 , 3 ]
ReadOnlySpan < int > span5 = array1 . AsSpan ( 2 , 3 ); // [ 3 , 4 , 5 ]

Console . WriteLine ( "比較結果:" );
Console . WriteLine ( $"span1 == span2:{span1 == span2}" ); // true - 同一內存
Console . WriteLine ( $"span1 == span3:{span1 == span3}" ); // false - 不同內存
Console . WriteLine ( $"span4 == span5:{span4 == span5}" ); // false - 不同內存區域

// 內容比較(需要手動實現)
bool contentsEqual = span1 . SequenceEqual ( span3 );
Console . WriteLine ( $"span1 . SequenceEqual ( span3 ):{contentsEqual}" ); // true - 內容相同

備註

兩個 ReadOnlySpan < T > 對象不等的條件是它們具有不同的長度,且 左 和 右 的對應元素指向不同的內存。

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.