翻译自 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); }
一、从索引 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
) 与 String
、Span<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
类型表示一个序列索引。^
),指定一个索引与序列末尾相关,用于构造 System.Index
对象。System.Range
类型表示序列的子范围。..
),用于指定范围的开始和末尾,就像操做数同样,用于构造 System.Range
对象。考虑数组 sequence
, 0
索引与 sequence[0]
相同。 ^0
索引与 sequence[sequence.Length]
相同。 请注意,sequence[..^0]
不会引起异常,就像 sequence[..sequence.Length]
同样。对于任意数字 n
,索引 ^n
与 sequence.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
译者 : 技术译民
出品 : 技术译站
连接 : 英文原文
http://www.javashuo.com/article/p-qqvmqtjv-nu.html "System.Index
结构体" ↩︎