C# 中 System.Range 結構體
阿新 • • 發佈:2020-10-13
> 翻譯自 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