C#8.0中System.Index和System.Range的本质论

编程入门 行业动态 更新时间:2024-10-09 10:29:35

C#8.0中System.Index和System.Range的<a href=https://www.elefans.com/category/jswz/34/1768327.html style=本质论"/>

C#8.0中System.Index和System.Range的本质论

1 简介

对数组或集合的引用都要使用索引,为了进一步规范对索引的使用,从C#8.0开始,提供了两个新的只读结构体 System.IndexSystem.Range ,这两个类的具体用法官方说的很清楚:C# 8中索引和范围,故对基本概念不再细表,请直接参见官方文档。
本文的核心任务是从本质上介绍这两个类的具体内容和原理

2 readonly struct System.Index

System.Index 是一个只读的结构体,其核心目的是用于表示集合中元素的位置。对位置的定义基本只有两种情况,即从左向右的位置和从右向左的位置。所以,Index使用以下两个属性用于索引表示:

  • int Value 索引的位置值;
  • bool IsFromEnd 索引是否从尾部开始计算。
    和唯一的方法 GetOffset(int length) 用于计算偏移量。
// 初始化
Index id1 = new Index(1); // 等价于 new Index(1, false)
Index id2 = 1;
Index id3 = new Index(2, true);
Index id4 = ^2;
Console.WriteLine($"The last word is {words[^1]}"); // 返回 "dog"

3 应用场景示例

直到C#8.0官方才给出索引的定义目的何在呢?让我们通过下面的示例来理解。
给定一个路径 var s = @"C:\Data\Device\DCT1052",请提取出最后一段目录的名称,即DCT1052,从左向右的提取方法是 s.Split('\\')[3]。这是在路径目录深度固定的情况下,如果是不固定的就会比较麻烦,代码需要编写如下:

var dirs = s.Split('\\');
var name = dirs[dirs.Length -1 ];

这样就需要使用2行代码表示,如果非要用1行,就必需写成:

var name = s.Split('\\')[s.Split('\\').Length -1 ];

但是这样写不仅拆分做了2次,而且也不优雅。

所以,为了解决这个问题,我们只需添加一种能够从右向左表示的方法即可,而Index就是这个目的,代码可以表示如下:

var name = s.Split('\\')[new Index(1, true)];

为了进一步简单,C#引入了hat(^)运算符,new Index(1, true) 可以表示成 ^1 从而使用语句简化为 s.Split('\\')[^1];,即:

var name = s.Split('\\')[^1];  // 对比 python更方便,可以直接使用-1

4 本质论

本质上 new Index(Value, IsFromEnd) 就是通过 IsFromEnd 指定了索引的计算方向,Value 表示偏移量,并不表示对实际数组的位置。所以,需要使用 GetOffset(length) 来计算集合长度为 length 时 索引的具体位置。当然,在从左向右数时,并不需要 length,只有在从右向左数时才需要。但是,为了逻辑上理解的统一,我们应该将Index只表示是一种偏移量,而不是具体在指定数组中的索引。实际上,这个操作在其他语言中根本不算新鲜,比如在Python中可以通过 value[-1]的方式实现从右向左的访问。

5 System.Range

有了以上的理解,Range也容易理解,就是使用两个Index分别表示范围的 Start 和 End 的左闭右开区间,即 [Start, End)。并可以提供了函数 (int Offset, int Length) Range.GetOffsetAndLength(length) 用于计算给定长度的区间的偏移量和长度。
示例1: (1…^1).GetOffsetAndLength(5) 表示从第1个到倒数第1个,即 [1, 4),表示从第1个表示的连续3个,与返回结果为 (1, 3) 一致;
示例2: (4…^3).GetOffsetAndLength(5) 与上面相同,但是 Start 的位置要小于 End,所以会报 Unhandled exception. System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values. (Parameter 'length') 错误。

参考

[1] 微软官网, C# 8中索引和范围
[2] 微软MSDN, 从末尾运算符 ^ 开始索引
[3] CSDN文章, 关于C# 8中的Hat运算符(^)

更多推荐

C#8.0中System.Index和System.Range的本质论

本文发布于:2024-02-06 04:31:24,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1746399.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:本质   System   Range   Index

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!