翻譯自 John Demetriou 2020年4月6日 的文章 《C# 8 Is Introducing Ranges》,補充了一些內容
我們之前討論過的 C# 中的一個特性 System.Index 結構體[1],與另一特性 System.Range 結構體 是攜手並進的。
在 C# 8.0 之前,沒有訪問集合中任意部分的范圍或切片的語法。開發人員通常不得不執行一些自定義的切片操作,或者依靠諸如 array.Skip(5).Take(2);
的 LINQ 方法。
現在 C# 添加了一個新的小特性,它可以幫助人們從一個大的數組項目中獲取一個小范圍的項目。
讓我們來考慮一下。假設我們有一個項目數組,我們僅需展示其中的一部分。通常情況下,我們只需要循環這部分,然后像下面這樣輸出它們。
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
),我們可以用以下方式來替換:
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
循環應該是:
foreach (var item in array[1..6])
{
Console.WriteLine(item);
}
Range 的一些示例
1、從索引 1(包含) 到末尾(包含)
foreach (var item in array[1..])
{
Console.WriteLine(item);
}
2、從開始(包含)到索引 3(不包含)
foreach (var item in array[..3])
{
Console.WriteLine(item);
}
3、結合以上兩種,您可以得到一個語法上正確的以下版本
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);
}
4、從索引 1(包含)到 從末尾開始的索引 1(不包含)
foreach (var item in array[1..^1])
{
Console.WriteLine(item);
}
在這里,它結合了[前面文章][1:1]中介紹的 Index
的 Hat 運算符(^
)。
一個快速的解釋,Hat 運算符(^
),會給您一個特定的索引。如果您寫 ^1
,也就是在請求最后一項的索引。如上所述,考慮到最后一個索引號是排除的,在一個有 10 項的序列中,請求索引項直到 ^1
,您也就是在請求索引項直到索引 9(索引從 0 開始),並且該項不包括在其中。
我希望我講清楚了。
將范圍作為變量
我們前面所做的是,將范圍(Range
)作為類型傳遞。我們也可以將范圍聲明為一個變量:
Range range = 1..9;
然后,可以在 [
和 ]
字符中使用該范圍:
var subarray = array[range];
我們還可以將其作為方法的參數傳遞、將其存儲為私有變量,或者用在任何業務邏輯所需的地方。
范圍的類型支持
范圍(Range
)不能被用在 List
或者 IEnumerable<T>
,但數組並不是唯一支持它的類型。
您還可以將索引(Index
)和范圍(Range
) 與 String
、Span<T>
[2] 或 ReadOnlySpan<T>
[3] 一起使用。
與字符串一起使用的例子基本上就是代替 Substring
方法,如下所示:
string s = "01234567";
string r = s[1..3]; // r 將會是 "12"
對於每個擔心 List
(它可能是您通常用來替代數組的類型)不支持范圍的人來說,List
從 .Net Framework 2.0 開始就已經有 GetRange
方法了。
以下為譯者補充
索引和范圍總結
索引(Index
)和范圍(Range
)為訪問序列中的單個元素或范圍提供了簡潔的語法。
對索引和范圍的語言支持依賴於兩個新類型和兩個新運算符:
System.Index
[4] 類型表示一個序列索引。- Hat 運算符(
^
),指定一個索引與序列末尾相關,用於構造System.Index
對象。 System.Range
[5] 類型表示序列的子范圍。- 范圍運算符(
..
),用於指定范圍的開始和末尾,就像操作數一樣,用於構造System.Range
對象。
考慮數組 sequence
, 0
索引與 sequence[0]
相同。 ^0
索引與 sequence[sequence.Length]
相同。 請注意,sequence[..^0]
不會引發異常,就像 sequence[..sequence.Length]
一樣。對於任意數字 n
,索引 ^n
與 sequence.Length - n
相同。 如下面代碼中的注釋所示:
var array = new string[]
{
// index from start index from end
"Item0", // 0 ^9
"Item1", // 1 ^8
"Item2", // 2 ^7
"Item3", // 3 ^6
"Item4", // 4 ^5
"Item5", // 5 ^4
"Item6", // 6 ^3
"Item7", // 7 ^2
"Item8", // 8 ^1
}; // 9 (or array.Length) ^0
一個范圍指定了范圍的“開始”和“末尾”。 范圍是左閉右開的,也就是說范圍包含“開始”,不包含“末尾”。
范圍 [0..sequence.Length]
、[0..^0]
和 [..]
都表示整個范圍。
作者 : John Demetriou
譯者 : 技術譯民
出品 : 技術譯站
鏈接 : 英文原文
https://www.cnblogs.com/ittranslator/p/13810800.html
System.Index
結構體和 Hat 運算符(^)的全新用法 ↩︎ ↩︎https://docs.microsoft.com/zh-cn/dotnet/api/system.span-1
Span<T>
↩︎https://docs.microsoft.com/zh-cn/dotnet/api/system.readonlyspan-1
ReadOnlySpan<T>
↩︎https://docs.microsoft.com/zh-cn/dotnet/api/system.index
System.Index
↩︎https://docs.microsoft.com/zh-cn/dotnet/api/system.range
System.Range
↩︎