1. 程式人生 > >C# 中 System.Range 結構體

C# 中 System.Range 結構體

> 翻譯自 John Demetriou 2020年4月6日 的文章 [《C# 8 Is Introducing Ranges》](http://www.devsanon.com/c/c-8-is-introducing-ranges/) 我們之前討論過的 C# 中的一個特性 [**System.Index 結構體**](https://mp.weixin.qq.com/s/k4qxPRaMRRUWal5muc0SQQ),與另一特性 **System.Range 結構體** 是攜手並進的。 在 C# 8.0 之前,沒有訪問集合中任意部分的範圍或切片的語法。開發人員通常不得不執行一些自定義的切片操作,或者依靠諸如 `array.Skip(5).Take(2);` 的 LINQ 方法。 現在 C# 添加了一個新的小特性,它可以幫助人們從一個大的陣列專案中獲取一個小範圍的專案。 讓我們來考慮一下。假設我們有一個專案陣列,我們僅需展示其中的一部分。通常情況下,我們只需要迴圈這部分,然後像下面這樣輸出它們。 ```csharp 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`),我們可以用以下方式來替換: ```csharp 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` 迴圈應該是: ```csharp foreach (var item in array[1..6]) { Console.WriteLine(item); } ``` ## Range 的一些示例 1、從索引 1(包含) 到末尾(包含) ```csharp foreach (var item in array[1..]) { Console.WriteLine(item); } ``` 2、從開始(包含)到索引 3(不包含) ```csharp foreach (var item in array[..3]) { Console.WriteLine(item); } ``` 3、結合以上兩種,您可以得到一個語法上正確的以下版本 ```csharp foreach (var item in array[..]) { Console.WriteLine(item); } ``` 它的意思是獲取整個範圍。 > 譯者注 > 它也等同於下面兩種寫法: ```csharp foreach (var item in array[0..^0]) { Console.WriteLine(item); } ``` ```csharp foreach (var item in array[0..array.Length]) { Console.WriteLine(item); } ``` 4、從索引 1(包含)到 *從末尾開始*的索引 1(不包含) ```csharp foreach (var item in array[1..^1]) { Console.WriteLine(item); } ``` 在這裡,它結合了[前面文章](https://mp.weixin.qq.com/s/k4qxPRaMRRUWal5muc0SQQ)中介紹的 `Index` 的 Hat 運算子(`^`)。 一個快速的解釋,Hat 運算子(`^`),會給您一個特定的索引。如果您寫 `^1`,也就是在請求最後一項的索引。如上所述,考慮到最後一個索引號是排除的,在一個有 10 項的序列中,請求索引項直到 `^1`,您也就是在請求索引項直到索引 9(索引從 0 開始),並且該項不包括在其中。 我希望我講清楚了。 ## 將範圍作為變數 我們前面所做的是,將範圍(`Range`)作為型別傳遞。我們也可以將範圍宣告為一個變數: ```csharp Range range = 1..9; ``` 然後,可以在 `[` 和 `]` 字元中使用該範圍: ```csharp var subarray = array[range]; ``` 我們還可以將其作為方法的引數傳遞、將其儲存為私有變數,或者用在任何業務邏輯所需的地方。 ## 範圍的型別支援 範圍(`Range`)不能被用在 `List` 或者 `IEnumerable<Τ>`,但陣列並不是唯一支援它的型別。 您還可以將索引(`Index`)和範圍(`Range`) 與 `String`、[`Span