C# 中 System.Range 结构体
翻译自 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
) 与 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
类型表示一个序列索引。- 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
译者 : 技术译民
出品 : 技术译站
链接 : 英文原文
C# 中 System.Range 结构体的更多相关文章
- C# 中 System.Index 结构体和 Hat 运算符(^)的全新用法
翻译自 John Demetriou 2019年2月17日 的文章 <C# 8 – Introducing Index Struct And A Brand New Usage For The ...
- 剔除list中相同的结构体数据
剔除list中相同的结构体数据,有三个思路:1.两层循环,逐个比较 2.使用set容器来剔除 3.使用unique方法去重 // deduplication.cpp : 定义控制台应用程序的入口点. ...
- MFC中的NMHDR结构体和NMUPDOWN结构体
建立spin控件,创建UDN_DELTAPOS一个消息函数后: void CSpinDlg::OnDeltaposSpin1(NMHDR* pNMHDR, LRESULT* pResult) { NM ...
- C语言中 不定义结构体变量求成员大小
所谓的求成员大小, 是求成员在该结构体中 用 sizeof(结构体名.结构体成员名) 求来的. 很多时候我们需要知道一个结构体成员中的某个成员的大小, 但是我们又不需要定义该结构体类型的变量(定义的话 ...
- 如何系统学习C 语言(中)之 结构体篇
1,结构体 在前面我们知道变量和数组都可以用来存储数据,变量用来存储单个数据,数组可以用来存储一组同类型的数据,但你有没有发现--它们都只适合单一属性的数据.那现实生活中,很多对象都是具有多属性的.例 ...
- 黑马程序员——Foundation中的OC结构体
<span style="font-size:14px">------<a target="_blank" href="http:/ ...
- 【2016-08-18】转载:总结C++中几种结构体初始化的方法
作者:Ac_Von 博客地址:http://www.cnblogs.com/vongang/ 文章地址:http://www.cnblogs.com/vongang/archive/2011/07/3 ...
- Objective-C中常用的结构体NSRange,NSPoint,NSSize(CGSize),NSRect
本节要点:红色标记 需要记下来 1 NSRange typedef struct _NSRange { NSUInteger location; NSUInteger length ...
- f2fs解析(七)node管理器中的 free_nid 结构体
除了node_info之外, node管理器中还有还有个重要的数据结构: struct free_nid { struct list_head list; /* for free node id li ...
随机推荐
- The Triangle (简单动态规划)
7 3 8 8 1 0 2 7 4 4 4 5 2 6 5 (Figure 1) Figure 1 shows a number triangle. Write a program that calc ...
- 一键部署k8s
本人学习安装kubernetes时,顺便整理了安装脚本,可以通过执行一个脚本,自动二进制安装好1台master+2台node的k8环境.方便需要学习k8s的同学. 百度网盘:https://pan.b ...
- Go Http包解析:为什么需要response.Body.Close()
简单来讲就是:为了提高效率,http.Get 等请求的 TCP 连接是不会关闭的(再次向同一个域名请求时,复用连接),所以必须要手动关闭. 2019-01-24 10:43:32 更新 不管是否使用 ...
- 嵌入式Linux软链接使用技巧
软链接概述 软链接是Linux下常用的一种共享文件方式.目录的方式,这种方式类似于Windows下的快捷方式.一般一个文件或者目录在不同的路径都需要的时候,可以通过创建软链接的方式来共享,这样只系统下 ...
- 必应API接口nodejs版
近期,在研究百度.必应.API等的url提交API时,发现有用Go语言做工具的大佬的分享 利用 API 自动向搜索引擎提交网址(Go语言版) - pyList. 其中提到bing API提交方法,并给 ...
- C#开发PACS医学影像处理系统(十四):处理Dicom影像窗宽窗位
概念解释(网络资料): 窗宽: 窗宽指CT图像所显示的CT 值范围.在此CT值范围内的组织结构按其密度高低从白到黑分为16 个灰阶以供观察对比.例如,窗宽选定为100 Hu ,则人眼可分辨的CT值为1 ...
- Spring注解不生效原因总结
在Spring的注解学习中发现使用(@Resource.@PostConstruct. @PreDestroy)这三个注解时不生效.使用@Resource发生空指针异常,说 明被注解对象没有被成功注入 ...
- Docker实战(3):Tomcat部署
运行环境:centos7,Docker version 1.13.1,docker tomcat version 8.5.50 创建文件(为映射文件做准备,非固定) mkdir -p /tomcat/ ...
- k8s Docker 安装
k8s Docker 安装 一.运行环境 Centos 7.7 虚拟机内核为 3.10 基础组件版本: k8s.gcr.io/kube-apiserver:v1.16.0 k8s.gcr.io/kub ...
- 现在有T1、T2、T3三个线程,你怎样保证T2在T1执行完后执行,T3在T2执行完后执行?
Thread t1 = new Thread(new T1()); Thread t2 = new Thread(new T2()); Thread t3 = new Thread(new T3()) ...