C# 中 System.Range 結構體

翻譯自 John Demetriou 2020年4月6日 的文章 《C# 8 Is Introducing Ranges》html

咱們以前討論過的 C# 中的一個特性 System.Index 結構體[1],與另外一特性 System.Range 結構體 是攜手並進的。api

在 C# 8.0 以前,沒有訪問集合中任意部分的範圍或切片的語法。開發人員一般不得不執行一些自定義的切片操做,或者依靠諸如 array.Skip(5).Take(2); 的 LINQ 方法。數組

如今 C# 添加了一個新的小特性,它能夠幫助人們從一個大的數組項目中獲取一個小範圍的項目。ui

讓咱們來考慮一下。假設咱們有一個項目數組,咱們僅需展現其中的一部分。一般狀況下,咱們只須要循環這部分,而後像下面這樣輸出它們。spa

var array = new string[]
    {
        "Item0",
        "Item1",
        "Item2",
        "Item3",
        "Item4",
        "Item5",
        "Item6",
        "Item7",
        "Item8",
        "Item9"
    };

for (int i = 1; i <= 5; i++)
{
    Console.WriteLine(array[i]);
}

所以當咱們僅須要幾個特定的項,咱們經過控制索引值來獲取它們。翻譯

經過使用範圍(Range),咱們能夠用如下方式來替換:code

var array = new string[]
    {
        "Item0",
        "Item1",
        "Item2",
        "Item3",
        "Item4",
        "Item5",
        "Item6",
        "Item7",
        "Item8",
        "Item9"
    };

foreach (var item in array[1..5])
{
    Console.WriteLine(item);
}

在這裏,第一次使用的人會注意到一個奇怪的狀況——它只會打印四項。爲何呢?這是由於範圍(Range)包含開始,但不包含末尾
若是想要與上面的 for 循環有相同的結果,咱們的 foreach 循環應該是:htm

foreach (var item in array[1..6])
{
    Console.WriteLine(item);
}

Range 的一些示例

一、從索引 1(包含) 到末尾(包含)對象

foreach (var item in array[1..])
{
    Console.WriteLine(item);
}

二、從開始(包含)到索引 3(不包含)blog

foreach (var item in array[..3])
{
    Console.WriteLine(item);
}

三、結合以上兩種,您能夠獲得一個語法上正確的如下版本

foreach (var item in array[..])
{
    Console.WriteLine(item);
}

它的意思是獲取整個範圍。

譯者注
它也等同於下面兩種寫法:

foreach (var item in array[0..^0])
{
    Console.WriteLine(item);
}
foreach (var item in array[0..array.Length])
{
    Console.WriteLine(item);
}

四、從索引 1(包含)到 從末尾開始的索引 1(不包含)

foreach (var item in array[1..^1])
{
    Console.WriteLine(item);
}

在這裏,它結合了前面文章中介紹的 Index 的 Hat 運算符(^)。

一個快速的解釋,Hat 運算符(^),會給您一個特定的索引。若是您寫 ^1,也就是在請求最後一項的索引。如上所述,考慮到最後一個索引號是排除的,在一個有 10 項的序列中,請求索引項直到 ^1,您也就是在請求索引項直到索引 9(索引從 0 開始),而且該項不包括在其中。
我但願我講清楚了。

將範圍做爲變量

咱們前面所作的是,將範圍(Range)做爲類型傳遞。咱們也能夠將範圍聲明爲一個變量:

Range range = 1..9;

而後,能夠在 [] 字符中使用該範圍:

var subarray = array[range];

咱們還能夠將其做爲方法的參數傳遞、將其存儲爲私有變量,或者用在任何業務邏輯所需的地方。

範圍的類型支持

範圍(Range)不能被用在 List 或者 IEnumerable<Τ>,但數組並非惟一支持它的類型。

您還能夠將索引(Index)和範圍(Range) 與 StringSpan<T>ReadOnlySpan<T> 一塊兒使用。

與字符串一塊兒使用的例子基本上就是代替 Substring 方法,以下所示:

string s = "01234567";
string r = s[1..3]; // r 將會是 "12"

對於每一個擔憂 List(它多是您一般用來替代數組的類型)不支持範圍的人來講,List 從 .Net Framework 2.0 開始就已經有 GetRange 方法了。




如下爲譯者補充

索引和範圍總結

索引(Index)和範圍(Range)爲訪問序列中的單個元素或範圍提供了簡潔的語法。

對索引和範圍的語言支持依賴於兩個新類型兩個新運算符

  • System.Index 類型表示一個序列索引。
  • Hat 運算符(^),指定一個索引與序列末尾相關,用於構造 System.Index 對象。
  • System.Range 類型表示序列的子範圍。
  • 範圍運算符(..),用於指定範圍的開始和末尾,就像操做數同樣,用於構造 System.Range 對象。

考慮數組 sequence0 索引與 sequence[0] 相同。 ^0 索引與 sequence[sequence.Length] 相同。 請注意,sequence[..^0] 不會引起異常,就像 sequence[..sequence.Length] 同樣。對於任意數字 n,索引 ^nsequence.Length - n 相同。 以下面代碼中的註釋所示:

string[] words = new string[]
{
                // index from start    index from end
    "The",      // 0                   ^9
    "quick",    // 1                   ^8
    "brown",    // 2                   ^7
    "fox",      // 3                   ^6
    "jumped",   // 4                   ^5
    "over",     // 5                   ^4
    "the",      // 6                   ^3
    "lazy",     // 7                   ^2
    "dog"       // 8                   ^1
};              // 9 (or words.Length) ^0

一個範圍指定了範圍的「開始」「末尾」。 範圍是左閉右開的,也就是說範圍包含「開始」,不包含「末尾」
範圍 [0..sequence.Length][0..^0][..] 都表示整個範圍。


做者 : John Demetriou
譯者 : 技術譯民
出品 : 技術譯站
連接 : 英文原文


  1. http://www.javashuo.com/article/p-qqvmqtjv-nu.html "System.Index 結構體" ↩︎

相關文章
相關標籤/搜索