C#范围表达式,模式匹配,逆变和协变--11

目录

一.范围表达式

1.概述

2.语法

3.代码示例

 4.实现原理

5.应用场景

二.模式匹配

1.概述

2.核心概念

3.常用模式类型

4.Switch表达式

5.使用示例

6.优势

三.逆变和协变

1.概述

2.泛型类型参数的变性

3.协变示例

4.逆变示例

5.注意事项

6.应用场景

总结


一.范围表达式

1.概述

  • 范围表达式是C# 8.0引入的新特性,它提供了一种简洁的语法来表示数组,字符串或任何实现了索引器的集合类型的子范围(slice).通过范围表达式,可以更方便地从集合中提取出特定范围的元素

2.语法

  • startIndex..endIndex:表示从startIndex开始(包含),到endIndex结束(不包含)的元素
  • ..endIndex:表示从集合的起始位置到endIndex(不包含)的元素
  • startIndex..:表示从startIndex开始(包含)到集合的末尾的所有元素
  • ..:表示集合中的所有元素

注意:索引可以是正数,也可以是使用^符号表示的从末尾开始的索引,其中^1表示最后一个元素

3.代码示例

int[] numbers = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };// 从索引2(值为2)到索引5(值为5),不包含索引5   
int[] slice1 = numbers[2..5]; // {2, 3, 4}// 从开始到索引3(不包含索引3)   
int[] slice2 = numbers[..3]; // {0, 1, 2}// 从索引5到结尾   
int[] slice3 = numbers[5..]; // {5, 6, 7, 8, 9}// 获取最后两个元素   
int[] slice4 = numbers[^2..]; // {8, 9}// 获取从索引1到倒数第二个元素   
int[] slice5 = numbers[1..^1]; // {1, 2, 3, 4, 5, 6, 7, 8}

 4.实现原理

范围表达式使用了System.Index和System.Range结构:

  • Index:表示一个索引位置,可以从开头(从0开始)或从结尾(使用^符号)计数
  • Range:由Index的起始和结束位置组成,表示一个范围

编译器会将范围表达式转换为调用Slice方法或其他适当的方法.例如numbers[2..5]会转换为numbers.Slice(2, 3)

在C#中,Slice方法是与Span<T>和ReadonlySpan<T>类型相关的功能,用于在不复制数据的情况下生成一个子序列.这种方法在处理大型数据集或需要高性能操作时特别有用,因为它避免了不必要的数据复制

基本用法:

using System;class Program   
{static void Main(){int[] array = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };Span<int> span = array; // 创建一个 Span<int> 包含整个数组// 从索引2开始,取3个元素Span<int> slice = span.Slice(2, 3);foreach (var item in slice){Console.WriteLine(item); // 输出: 3 4 5}}   
}

5.应用场景

  • 字符串处理:
string text = "Hello, World!";   
string subText = text[7..^1]; // "World"
  • 列表和视图:

如果列表实现了Slice方法或索引器支持Range则也可以使用范围表达式

二.模式匹配

1.概述

  • 模式匹配是C#从7.0版本开始引入的特性,用于更简洁地表达类型检查,解构和条件判断.在C# 8.0及后续版本中,模式匹配得到了进一步增强,使代码更加清晰和易读

2.核心概念

  • 模式(Pattern):描述需要匹配的特定形状或条件,例如类型,值,属性等
  • 表达式(Expression):应用模式匹配的对象或值\

3.常用模式类型

恒值模式:匹配特定的常量值

if (obj is null)
{// obj为null
}

类型模式:检查对象是否为特定类型,并进行类型转换

if (obj is string s)
{// obj是string类型,且已转换为s
}

属性模式:检查对象的属性是否满足特定条件

if (person is { Age: >= 18 })
{// person的Age属性大于等于18
}

位置模式:对对象进行解构,并匹配解构后的值

if (point is (0, 0))
{// point在原点
}

递归模式:在模式中嵌套使用其他模式

if (tree is Node(var left, var right))
{// 对左子树和右子树进行处理
}

4.Switch表达式

C# 8.0引入了新的Switch表达式,更加简洁:

代码示例:

string GetShapeDescription(Shape shape) => shape switch   
{Circle { Radius: var r } => $"这是一个半径为{r}的圆形",Rectangle { Width: var w, Height: var h } => $"这是一个宽{w}高{h}的矩形",_ => "未知形状"    
};    

5.使用示例

类型检查和转换:

 if (obj is int number){Console.WriteLine($"整数:{number}");}

属性匹配:

if (employee is { Position: "Manager", Salary: > 5000 })
{// 匹配职位为Manager且薪水大于5000的员工
}

6.优势

  • 增强可读性:使条件判断更加直观
  • 减少类型转换代码:自动进行类型转换,减少冗余代码
  • 支持复杂条件:可以嵌套和组合多种模式,表达复杂的匹配逻辑

三.逆变和协变

1.概述

协变和逆变用于解决泛型类型在继承关系中的转换问题,主要应用于泛型接口和泛型委托.它们允许你在泛型类型之间进行类型转换,而不需要创建新的类型或进行显式转换

  • 协变(Covariance):允许从派生类型转换为基类型(输出位置)
  • 逆变(Contravariance):允许从基类型转换为派生类型(输入位置)

2.泛型类型参数的变性

在泛型接口或委托中,可以使用out和in关键字来声明类型参数的变性:

  • out:协变类型参数,只能用于返回值(输出)
  • in:逆变类型参数,只能用于参数(输入)

3.协变示例

协变接口:

public interface IEnumerable<out T>{IEnumerator<T> GetEnumerator();}

由于T被声明为out,因此IEnumerable<string>可以赋值给IEnumerable<object>:

IEnumerable<string> strings = new List<string>();
IEnumerable<object> objects = strings; // 合法,协变

协变委托:

public delegate T Factory<out T>();

使用示例:

Factory<string> stringFactory = () => "Hello";
Factory<object> objectFactory = stringFactory; // 合法,协变

4.逆变示例

逆变接口:

public interface IComparer<in T>{int Compare(T x, T y);}

由于T被声明为in,因此IComparer<object>可以赋值给IComparer<string>:

IComparer<object> objectComparer = new MyObjectComparer();
IComparer<string> stringComparer = objectComparer; // 合法,逆变

逆变委托:

public delegate void Action<in T>(T item);

使用示例:

Action<object> objectAction = obj => Console.WriteLine(obj);
Action<string> stringAction = objectAction; // 合法,逆变

5.注意事项

  • 限制:变性只能用于接口和委托的类型参数,且类型参数只能用于输入位置(逆变)或输出位置(协变),不能同时用于输入和输出
  • 类和结构体:泛型类和结构体的类型参数不支持变性
  • 方法类型参数:泛型方法的类型参数也不支持变性

6.应用场景

  • 接口的扩展:通过协变和逆变,可以设计更灵活的接口,使之更通用
  • 事件处理程序:在委托中使用变性,可以赋值兼容的委托实例
  • 泛型集合:在处理泛型集合时,可以更方便地进行类型转换

总结

  • 协变适用于从派生类型转换为基类型(类型参数用于输出)
  • 逆变适用于从基类型转换为派生类型(类型参数用于输入)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/630.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python迷宫寻宝 第4关 自动寻路(找宝箱、宝石、终点、获取企鹅信息)

目录 地图 ​编辑 1、成功获取粉宝石或黄宝石。 2、获取企鹅的信息 3、获取红宝石 (1)api.get.item获取红宝石 (2)context.items获取红宝石 4、获取宝箱 &#xff08;1&#xff09;api.get.item获取宝箱 &#xff08;2&#xff09;context.items获取宝箱 5、达到终点 …

慧集通(DataLinkX)iPaaS集成平台-业务建模之业务对象(二)

3.UI模板 当我们选择一条已经建好的业务对象点击功能按钮【UI模板】进入该业务对象的UI显示配置界面。 右边填写的是UI模板的编码以及对应名称&#xff1b;菜单界面配置以业务对象UI模板编码获取显示界面。 3.1【列表-按钮】 展示的对应业务对象界面的功能按钮配置&#xff1…

PyCharm 引用其他路径下的文件报错 ModuleNotFound 或报红

PyCharm 中引用其他路径下的文件提示 ModuleNotFound&#xff0c;将被引用目录添加到系统路径&#xff1a; # # 获取当前目录 dir_path os.path.dirname(os.path.realpath(__file__)) # # 获取上级目录 parent_dir_path os.path.abspath(os.path.join(dir_path, os.pardir))…

mysql本地安装和pycharm链接数据库操作

MySQL本地安装和相关操作 Python相关&#xff1a;基础、函数、数据类型、面向、模块。 前端开发&#xff1a;HTML、CSS、JavaScript、jQuery。【静态页面】 Java前端&#xff1b; Python前端&#xff1b; Go前端 -> 【动态页面】直观&#xff1a; 静态&#xff0c;写死了…

单片机Day1

目录 一.什么是单片机&#xff1f; 二.单片机的组成 三.封装形式 四.优势 五.分类 通用型&#xff1a; 专用型&#xff1a; 按处理的二进制位可以分为&#xff1a; 六.应用&#xff1a; 七.发展趋势 1.增加CPU的数据总线宽度。 2.存储器的发展。 3.片内1/0的改进 …

spring ApplicationContextAware的使用和执行时机

实际项目开发中&#xff0c;会写类似如下的工具类&#xff0c;方便做脚本执行或者一些判断&#xff0c;提供一些api方法等(可阅读&#xff1a;https://blog.csdn.net/qq_26437925/article/details/114213391 &#xff0c;ApplicationContextAware就大派用场了)&#xff0c;如下…

Pytorch导出onnx模型并在C++环境中调用(含python和C++工程)

Pytorch导出onnx模型并在C环境中调用&#xff08;含python和C工程&#xff09; 工程下载链接&#xff1a;Pytorch导出onnx模型并在C环境中调用&#xff08;python和C工程&#xff09; 机器学习多层感知机MLP的Pytorch实现-以表格数据为例-含数据集和PyCharm工程中简单介绍了在…

2025新春烟花代码(二)HTML5实现孔明灯和烟花效果

效果展示 源代码 <!DOCTYPE html> <html lang"en"> <script>var _hmt _hmt || [];(function () {var hm document.createElement("script");hm.src "https://hm.baidu.com/hm.js?45f95f1bfde85c7777c3d1157e8c2d34";var …

[Transformer] The Structure of GPT, Generative Pretrained Transformer

The Structure of Generative Pretrained Transformer Reference: The Transformer architecture of GPT models How GPT Models Work

使用MATLAB正则表达式从文本文件中提取数据

使用MATLAB正则表达式从文本文件中提取数据 使用Python正则表达式从文本文件中提取数据的代码请看这篇文章使用正则表达式读取文本数据【Python】-CSDN博客 文本数据格式 需要提取 V 后面的数据, 并绘制出曲线. index 1V 0.000000W 0.000000E_theta 0.000000UINV 0.0…

电脑提示directx错误导致玩不了游戏怎么办?dx出错的解决方法

想必大家都有过这样的崩溃瞬间&#xff1a;满心欢喜打开心仪的游戏&#xff0c;准备在虚拟世界里大杀四方或者畅游冒险&#xff0c;结果屏幕上突然弹出个 DirectX 错误的提示框&#xff0c;紧接着游戏闪退&#xff0c;一切美好戛然而止。DirectX 作为 Windows 系统下游戏运行的…

python学opencv|读取图像(三十二)使用cv2.getPerspectiveTransform()函数制作透视图-变形的喵喵

【1】引言 前序已经对图像展开了平移、旋转缩放和倾斜拉伸技巧探索&#xff0c;相关链接为&#xff1a; python学opencv|读取图像&#xff08;二十八&#xff09;使用cv2.warpAffine&#xff08;&#xff09;函数平移图像-CSDN博客 python学opencv|读取图像&#xff08;二十…

初学spring 框架(了解spring框架的技术背景,核心体现,入门案例)

目录 技术背景 为什么要学习spring 框架&#xff1f; 学习spring 框架可以解决什么问题&#xff1f; 了解spring框架的核心体现 入门案例 步骤 1 导入 依赖 2 搭建三层架构体现【根据实际情况 构建】 3 添加配置文件 Test 测试类中 从 Ioc 容器 获取 Student 对象 总…

用户界面的UML建模11

然而&#xff0c;在用户界面方面&#xff0c;重要的是要了解《boundary》类是如何与这个异常分层结构进行关联的。 《exception》类的对象可以作为《control》类的对象。因此&#xff0c;《exception》类能够聚合《boundary》类。 参见图12&#xff0c;《exception》Database…

IDEA的常用设置

目录 一、显示顶部工具栏 二、设置编辑区字体按住鼠标滚轮变大变小&#xff08;看需要设置&#xff09; 三、设置自动导包和优化导入的包&#xff08;有的时候还是需要手动导包&#xff09; 四、设置导入同一个包下的类&#xff0c;超过指定个数的时候&#xff0c;合并为*&a…

STM32-笔记39-SPI-W25Q128

一、什么是SPI&#xff1f; SPI是串行外设接口&#xff08;Serial Peripheral Interface&#xff09;的缩写&#xff0c;是一种高速的&#xff0c;全双工&#xff0c;同步的通信总线&#xff0c;并且 在芯片的管脚上只占用四根线&#xff0c;节约了芯片的管脚&#xff0c;同时为…

uniapp小程序中隐藏顶部导航栏和指定某页面去掉顶部导航栏小程序

uniappvue3开发小程序过程中隐藏顶部导航栏和指定某页面去掉顶部导航栏方法 在page.json中 "globalStyle": {"navigationStyle":"custom",}, 如果是指定某个页面关闭顶部导航栏&#xff0c;在style中添加"navigationStyle": "cus…

【电子通识】PWM驱动让有刷直流电机恒流工作

电机的典型驱动方法包括电压驱动、电流驱动以及PWM驱动。本文将介绍采用PWM驱动方式的恒流工作。 首先介绍的是什么是PWM驱动的电机恒流工作&#xff0c;其次是PWM驱动电机恒流工作时电路的工作原理。 PWM驱动 当以恒定的电流驱动电机时&#xff0c;电机会怎样工作呢&#xff1…

Mysql--运维篇--主从复制和集群(主从复制I/O线程,SQL线程,二进制日志,中继日志,集群NDB)

一、主从复制 MySQL的主从复制&#xff08;Master-Slave Replication&#xff09;是一种数据冗余和高可用性的解决方案&#xff0c;它通过将一个或多个从服务器&#xff08;Slave&#xff09;与主服务器&#xff08;Master&#xff09;同步来实现。主从复制的基本原理是&#…

Mac 删除ABC 输入法

参考链接&#xff1a;百度安全验证 Mac下删除系统自带输入法ABC&#xff0c;正解&#xff01;_mac删除abc输入法-CSDN博客 ABC 输入法和搜狗输入法等 英文有冲突~~ 切换后还会在英文状态&#xff0c;可以删除 &#xff1b;可能会对DNS 输入有影响&#xff0c;但是可以通过复…