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

我们之前讨论过的 C# 中的一个特性 System.Index 结构体,与另一特性 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);
}

在这里,它结合了前面文章中介绍的 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 对象。

考虑数组 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
译者 :技术译民
出品 :技术译站(https://ITTranslator.cn/)

END

C# 中 System.Range 结构体相关推荐

  1. C# 中 System.Index 结构体和 Hat 运算符(^)的全新用法

    翻译自 John Demetriou 2019年2月17日 的文章 <C# 8 – Introducing Index Struct And A Brand New Usage For The ...

  2. (15)System Verilog结构体struct详解

    (15)System Verilog结构体struct详解 1.1 目录 1)目录 2)FPGA简介 3)System Verilog简介 4)System Verilog结构体struct详解 5) ...

  3. Java中如何实现结构体?如何对结构体进行排序?

    ***今天在做老师布置的编程题时,遇到了本题.感觉这道题如果用C++来解决的话,用结构体比较好吧!哈哈哈,可能还有其他的好方法,但我目前想到的是用结构体来解决比较合理.Java中有结构体吗?如果有,它 ...

  4. Swift 中枚举、结构体、类(enum、struct、class)

    Swift 中枚举.结构体.类(enum.struct.class) Swift中的枚举与OC相比不会自动分配初始值,值的类型不会限定为整数,可以给定关联值类型和具体值(整型.浮点型.字符型(Swif ...

  5. 函数体中定义的结构体和类型

    源代码: 1 #include <stdio.h> 2 struct smonth // point 1 3 { 4 int a; 5 int b; 6 }; 7 8 int func1( ...

  6. Python中定义(声明)结构体

    文章目录 前言 实现 前言 在Python中并无像C/C++那样的结构体类型,但是由于Python是用C编写而来的,很多东西可以互通. Python是有struct模块,但并非是用于处理一般结构体的, ...

  7. soap协议中的soap结构体

    soup协议中的soap结构体 struct SOAP_STD_API soap { short state; /* 0 = uninitialized, 1 = initialized, 2 = c ...

  8. c语言怎么判定结构体有无数据,C语言中什么是结构体,怎么定义结构体。

    为什么要用结构体? 没有结构体之前,C语言中,数据的组织依靠:变量+数组.最初最简单的时候,只需要使用基本数据类型来定义单个变量,需要几个就定义几个,后来有时候需要很多意义相关的变量这时候数组出现了. ...

  9. Linux中网络通信中 使用的结构体

    "+++++++++++++++++++++++++ Linux TCP/UDP通信中的结构体 +++++++++++++++++++++++++++++++++++++++" s ...

最新文章

  1. 高并发系列:存储优化之也许可能是史上最详尽的分库分表文章之一
  2. 别做菜鸟!莫让摄像头参数迷惑头脑
  3. 【数据竞赛】十组不同类型的组合特征!
  4. 09 Softmax 回归 + 损失函数 + 图片分类数据集【动手学深度学习v2】
  5. bootstrap到底是用来做什么的(概念)
  6. java -jar 默认参数_JAVA入门学习指南,建议收藏
  7. FYFG的完整形式是什么?
  8. 设计模式(结构型模式)——装饰模式(Decorator)
  9. ubuntu18.04安装opencv4.3.0
  10. opensource项目_最佳Opensource.com:硬件
  11. SPLUNK 安装配置及常用语法
  12. 疯狂java实验五数据流编程_2017-2018-2 20165209 实验五《网络编程与安全》实验报告...
  13. Android的logger机制分析
  14. pip install报错_【Python】pip install django报错
  15. P2962 [USACO09NOV]灯Lights 对抗搜索
  16. ionic的弹出框---和$ionicModal
  17. mysql中year函数算年龄_MySQL中的YEAR函数
  18. Numpy创建正态分布和均匀分布
  19. IGraphicsContain 删除元素
  20. PMP-项目成本管理

热门文章

  1. PHP 多维数组转json对象
  2. word-vba-microsoft(中英文)
  3. 网络相关配置,SSH服务,bash, 元字符
  4. Ubuntu16.04换源
  5. 触发器的创建、修改和删除
  6. extjs 前端js代码调用后台函数方法
  7. 解题报告 树形图计数
  8. 技术总监谈好的程序员如何写代码
  9. python图片内容长度识别_Python实现识别图片内容的方法分析
  10. 用SmarterFox替换Internet Explorer的“加速器”