前言

《C# 8.0 中使用 Index 和 Range》这篇中有人提出^0是什么意思?处于好奇就去试了,结果抛出异常。查看官方文档说^0索引与 sequence[sequence.Length] 相同,表达式 sequence[^0] 不会引发异常,就像 sequence[sequence.Length] 一样。但是在实际使用[^0]的时候抛出IndexOutOfRangeException的异常,很疑惑究竟是什么原因?

先说一下 C# 8.0 新增的两个新类型和两个新运算符,允许构造System.Index和System.Range对象,并在运行时索引/切片集合。

一、System.Index和System.Range结构

1、Index

表示一种可用于从开头或从结尾索引集合的类型。

public struct Index : IEquatable<Index> 

示例代码

string [] myArray = new string[5] { "A", "B", "C", "D", "E" };
string strArray= myArray[^1]; // strArray = E

代码中使用末尾运算符^和Index类型,myArray[ ^1] 表示从数组的倒数第一个元素,也就是从末尾开始算的第一个元素,所以最终结果是:E。

Hat运算符(^)的索引,指定一个索引与序列末尾相关。

2、Range

表示具有起始索引和结束索引的范围。

public struct Range : IEquatable<Range>

示例代码

string[] myArray = new string[5] { "A", "B", "C", "D", "E" };
string[] strArray = myArray[0..2]; // { A, B }

代码中使用范围运算符(..)和Range类型,myArray[0..2]表示把myArray这个序列,从索引为0的元素一直找到索引为2(但不包括索引2)的元素提取出来组成新的数组,所以最终结果是: {A,B}。

范围运算符(..),用于指定范围的开始和末尾,就像操作数一样。

Range类型范围运算符包含start不包含end。eg:myArray[0..2]包含索引0不包含索引2

3、Index和Range组合使用

尝试在Range的两端混合使用"从开始"和"从末尾"的Index,看看会发生什么?

var strNum = new string[]
{
// index from start index from end
"A", // 0 ^9
"B", // 1 ^8
"C", // 2 ^7
"D", // 3 ^6
"E", // 4 ^5
"F", // 5 ^4
"G", // 6 ^3
"H", // 7 ^2
"I" // 8 ^1
}; // 9 (strNum.Length) ^0
foreach (var item in strNum[0..^1])
Console.Write($"{item}");
foreach (var item in strNum[1..^0])
Console.Write($"{item}");
foreach (var item in strNum[0..^0])
Console.Write($"{item}");

输出结果:

ABCDEFGH
BCDEFGHI
ABCDEFGHI

0..^1 与 ..^1   相同 表示从0索引位置到末尾开始算的第1个元素

1.. 与 1..^0    相同 表示从1索引位置到末尾开始算的第0个元素

.. 与  0..^0   相同  表示全部从头到尾

二、[^0]会抛异常

1、[^1] 示例代码

int[] myArray = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int num = myArray[^1]; //num=10

2、[^0]示例代码

int[] myArray = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int num = myArray[^0]; //抛异常

代码结果如下图所示:

 官方文档描述:请考虑数组 sequence。 0 索引与 sequence[0] 相同。 ^0 索引与 sequence[sequence.Length] 相同。 表达式 sequence[^0]不会引发异常,就像 sequence[sequence.Length] 一样。 对于任何数字 n,索引 ^n 与 sequence[sequence.Length - n] 相同。

通过自己搜索到合理的解释 Index 类型 从尾部开始的索引是从1开始的,与序列的长度相关,那么意思就说单独使用末尾运算符时索引只能从1开始。

三、遗留问题

使用末尾运算符时索引只能从1开始,但是Index和Range组合使用时可以从0开始,目前还没有找到具体原因,如果大家有好的解释和方法,欢迎留言沟通和交流。

四、总结

1、Range类型  运算符(..)包括Start不包括End

2、Index类型 末尾运算符(^)

· 从头开始的索引是从0开始的

    · 从尾部开始的索引是从1开始的,与序列的长度相关

3、减少 SubString 的使用,eg:var str="12345"截取后三位,之前写法str.Substring(2,3),新语法str[^3..]

4、使用^和..这两个语法糖,让代码更加干净,可读,易维护

优秀是一种习惯,欢迎大家关注学习 

说说C# 8.0 新增功能Index和Range的^0是什么?的更多相关文章

  1. C#基础拾遗系列之二:使用ILSpy探索C#7.0新增功能点

    C#基础拾遗系列之二:使用ILSpy探索C#7.0新增功能点   第一部分: C#是一种通用的,类型安全的,面向对象的编程语言.有如下特点: (1)面向对象:c# 是面向对象的范例的一个丰富实现, 它 ...

  2. C#2.0新增功能06 协变和逆变

    连载目录    [已更新最新开发文章,点击查看详细] 在 C# 中,协变和逆变能够实现数组类型.委托类型和泛型类型参数的隐式引用转换. 协变保留分配兼容性,逆变则与之相反. 以下代码演示分配兼容性.协 ...

  3. C#基础拾遗系列之二:C#7.0新增功能点

    第一部分: C#是一种通用的,类型安全的,面向对象的编程语言.有如下特点: (1)面向对象:c# 是面向对象的范例的一个丰富实现, 它包括封装.继承和多态性.C#面向对象的行为包括: 统一的类型系统 ...

  4. C#7.0新增功能点

    原文地址:  https://www.cnblogs.com/runningsmallguo/p/8972678.html 第二部分:C#7.0新增的功能 (1)数字字面量的提升: C#7中的数字文字 ...

  5. C#2.0新增功能01 分布类与分部方法

    连载目录    [已更新最新开发文章,点击查看详细] 分部类型 拆分一个类.一个结构.一个接口或一个方法的定义到两个或更多的文件中, 每个源文件包含类型或方法定义的一部分,编译应用程序时将把所有部分组 ...

  6. Android 7.0 新增功能和api

    Android 7.0 Nougat 为用户和开发者引入多种新功能.本文重点介绍面向开发者的新功能. 请务必查阅 Android 7.0 行为变更以了解平台变更可能影响您的应用的领域. 要详细了解 A ...

  7. C#8.0 新增功能

    连载目录    [已更新最新开发文章,点击查看详细] C#8.0提供了许多增强功能 01 Readonly 成员 可将 readonly 修饰符应用于结构的任何成员. 它指示该成员不会修改状态. 这比 ...

  8. C#7.0 新增功能

    连载目录    [已更新最新开发文章,点击查看详细] C# 7.0 向 C# 语言添加了许多新功能 01 out 变量 支持 out 参数的现有语法已在此版本中得到改进. 现在可以在方法调用的参数列表 ...

  9. Xcode 9.0 新增功能大全

    Xcode是用于为Apple TV,Apple Watch,iPad,iPhone和Mac创建应用程序的完整开发人员工具集.Xcode开发环境采用tvOS SDK,watchOS SDK,iOS SD ...

随机推荐

  1. mysql 查询出来的内容无法显示全部

    前几天在做查询的时候,由于使用了字段拼接,所以查出来的其中一列,数据很长,但是每次显示一定的长度后,后面的就无法显示 原因是因为mysql设置查询出来的长度,好像默认是1024,因为我使用的是yii2 ...

  2. Java基础知识面试题详解(2019年)

    文章目录 1. 面向对象和面向过程的区别 2. Java 语言有哪些特点? 3. 关于 JVM JDK 和 JRE 最详细通俗的解答 JVM JDK 和 JRE 4. Oracle JDK 和 Ope ...

  3. 精尽Spring MVC源码分析 - HandlerExceptionResolver 组件

    该系列文档是本人在学习 Spring MVC 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释 Spring MVC 源码分析 GitHub 地址 进行阅读 Spring 版本:5.2. ...

  4. 很多人不知道的Python 炫技操作:条件语句的写法

    有的人说 Python 是一门 入门容易,但是精通难的语言,这一点我非常赞同. Python 语言里有许多(而且是越来越多)的高级特性,是 Python 发烧友们非常喜欢的.在这些人的眼里,能够写出那 ...

  5. [.NET] - 在Create一个RSA密钥的是要注意的长度问题

    有时候我们需要自己手动的创建RSA密钥,但是在密钥创建之后,在使用的时候会有类似密钥长度不正确的错误信息被抛出,那可能就是在创建一个RSA密钥的时候,对于的elements长度没设置正确,所以的ele ...

  6. 远程调用post请求和get请求

    /** * 获取用户 */ @RequestMapping("getUserMassages") public Map<String,Object> getuserMa ...

  7. java动态代理实现与原理详细分析(转)

    关于Java中的动态代理,我们首先需要了解的是一种常用的设计模式--代理模式,而对于代理,根据创建代理类的时间点,又可以分为静态代理和动态代理. 一.代理模式    代理模式是常用的java设计模式, ...

  8. Fragment学习

    利用Fragment可以动态的加载页面,减少Activity的数量. 便于开发 类似与html中FragmentSet一样 嵌套在一起,使每个页面为独立的 代码如下: package com.exam ...

  9. JAVADOC 文档注释命令

    简介 javadoc命令是用来生成自己API文档的 javadoc参数信息 @author 作者名 @version 版本号 @since 指明需要最早使用的jdk版本 @param 参数名 @ret ...

  10. Ubuntu/Liinux睡眠无法唤醒解决方法:ACPI设置

    最近给笔记本换了一个固态,顺便就重装了一下系统,版本是Ubuntu 20.10.装完之后各种功能基本都是正常的,触摸板轻触单击.双指右键等功能开箱即用.但是在安装完最新的Nvidia驱动之后就出现了问 ...