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.mzph.cn/diannao/66916.shtml

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

相关文章

ollama教程(window系统)

前言 在《本地大模型工具哪家强&#xff1f;对比Ollama、LocalLLM、LM Studio》一文中对比了三个常用的大模型聚合工具优缺点&#xff0c;本文将详细介绍在window操作系统下ollama的安装和使用。要在 Windows 上安装并使用 Ollama&#xff0c;需要依赖 NVIDIA 显卡&#xff0c…

代码随想录 字符串 test1

344. 反转字符串 - 力扣&#xff08;LeetCode&#xff09; 依次交换首尾。 class Solution { public:void reverseString(vector<char>& s) {int h,l;//首尾指针for(h 0, l s.size() - 1; h < s.size() / 2; h, l--){swap(s[h], s[l]);}return ;} };

[论文阅读] (35)TIFS24 MEGR-APT:基于攻击表示学习的高效内存APT猎杀系统

《娜璋带你读论文》系列主要是督促自己阅读优秀论文及听取学术讲座&#xff0c;并分享给大家&#xff0c;希望您喜欢。由于作者的英文水平和学术能力不高&#xff0c;需要不断提升&#xff0c;所以还请大家批评指正&#xff0c;非常欢迎大家给我留言评论&#xff0c;学术路上期…

半导体数据分析: 玩转WM-811K Wafermap 数据集(三) AI 机器学习

前面我们已经通过两篇文章&#xff0c;一起熟悉了WM-811K Wafermap 数据集&#xff0c;并对其中的一些数据进行了调用&#xff0c;生成了一些统计信息和图片。今天我们接着继续往前走。 半导体数据分析&#xff1a; 玩转WM-811K Wafermap 数据集&#xff08;二&#xff09; AI…

BGP 泄露

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 目录 1. BGP 是什么&#xff1f; 2. 什么是 BGP 泄露&#xff1f; 3. 今天发生了什么&#xff1f; 4. 正常和被劫持状态下的路由示意图 5. 受影响区域 6. 责任在谁&#xff1f; 7. 有办法避免这…

wireshark排除私接小路由

1.wireshark打开&#xff0c;发现了可疑地址&#xff0c;合法的地址段DHCP是192.168.100.0段的&#xff0c;打开后查看发现可疑地址段&#xff0c;分别是&#xff0c;192.168.0.1 192.168.1.174 192.168.1.1。查找到它对应的MAC地址。 ip.src192.168.1.1 2.通过show fdb p…

【Ubuntu与Linux操作系统:十一、Java与Android应用开发】

第11章 Java与Android应用开发 11.1 Java开发 Java是一种广泛使用的面向对象编程语言&#xff0c;以其平台无关性和强大的生态系统而闻名。它在Android开发中占据重要地位&#xff0c;同时也是企业级应用和服务器开发的首选语言。 1. Java语言的特点 跨平台性&#xff1a;Ja…

数据库序列的使用、常见场景与优劣势分析

在现代数据库系统中&#xff0c;唯一标识符&#xff08;如主键&#xff09;是数据表中不可或缺的一部分。为了确保主键的唯一性&#xff0c;数据库提供了多种方式来生成这些标识符。其中&#xff0c;数据库序列&#xff08;Sequence&#xff09; 是一种常用且灵活的生成唯一值的…

Rabbit Rocket kafka 怎么实现消息有序消费和延迟消费的

在消息队列系统中&#xff0c;像 RabbitMQ、RocketMQ 和 Kafka 这样的系统&#xff0c;都支持不同的方式来实现消息的有序消费和延迟消费。下面我们分别探讨这些系统中如何实现这两种需求&#xff1a; 1. RabbitMQ&#xff1a;实现消息有序消费和延迟消费 有序消费&#xff1…

Cesium加载地形

Cesium的地形来源大致可以分为两种&#xff0c;一种是由Cesium官方提供的数据源&#xff0c;一种是第三方的数据源&#xff0c;官方源依赖于Cesium Assets&#xff0c;如果设置了AccessToken后&#xff0c;就可以直接使用Cesium的地形静态构造方法来获取数据源CesiumTerrainPro…

kafka原理解析

一、基本概念与架构 消息&#xff08;Message&#xff09;&#xff1a;Kafka 中传递的数据单元&#xff0c;由消息头&#xff08;可选&#xff09;和消息体组成&#xff0c;消息体中包含了实际要传递的业务数据&#xff0c;例如用户的交易记录、日志信息等&#xff0c;通常以字…

26_Redis RDB持久化

从这个模块开始带领大家来学习Redis分布式缓存的相关内容,主要学习目标见下: 数据丢失问题:实现Redis数据持久化(RDB和AOF)并发能力问题:搭建Redis主从集群,实现读写分离故障恢复问题:利用Redis哨兵模式,实现健康检测和自动恢复存储能力问题:搭建Redis分片集群,利用…

使用 CompletableFuture 实现异步编程

在现代 Java 开发中&#xff0c;异步编程是一项重要技能。而 CompletableFuture 是从 Java 8 开始提供的一个功能强大的工具&#xff0c;用于简化异步任务的编写和组合。本文将详细介绍 CompletableFuture 的基本使用和一些常见的应用场景。 1. 为什么选择 CompletableFuture&…

操作系统进程同步

目录 1 进程同步的基本概念 1.1 进程同步概念的引入 1.1.1 两种形式的制约关系 1.1.2 临界资源 1.2 临界区问题 2 信号量机制 2.1 信号量机制介绍 2.1.1 整型信号量 2.1.2 记录型信号量 2.1.3 AND 型信号量 2.1.4 信号量集 2.2 信号量的应用 3 管程机制 3.1 管程…

宝塔面板 php8.0 安装 fileinfo 拓展失败

系统&#xff1a;Albaba Cloud Linux release 3 &#xff08;OpenAnolis Editon&#xff09;即 Centos 平替 异常提示&#xff1a; cc: fatal error: ** signal terminated program cc1 compilation terminated. make: *** [Makefile:211: libmagic/apprentice.lo] Error 1搜…

AWS云计算概览(自用留存,整理中)

目录 一、云概念概览 &#xff08;1&#xff09;云计算简介 &#xff08;2&#xff09;云计算6大优势 &#xff08;3&#xff09;web服务 &#xff08;4&#xff09;AWS云采用框架&#xff08;AWS CAF&#xff09; 二、云经济学 & 账单 &#xff08;1&#xff09;定…

【江协STM32】10-4/5 I2C通信外设、硬件I2C读写MPU6050

1. I2C外设简介 STM32内部集成了硬件I2C收发电路&#xff0c;可以由硬件自动执行时钟生成、起始终止条件生成、应答位收发、数据收发等功能&#xff0c;减轻CPU的负担支持多主机模型支持7位/10位地址模式支持不同的通讯速度&#xff0c;标准速度(高达100 kHz)&#xff0c;快速…

Web开发中页面出现乱码的解决(Java Web学习笔记:需在编译时用 -encoding utf-8)

目录 1 引言2 乱码表现、原因分析及解决2.1 乱码表现2.2 原因分析2.3 解决 3 总结 1 引言 Web开发的页面出现了乱码&#xff0c;一直不愿写出来&#xff0c;因为网上的解决方案太多了。但本文的所说的页面乱码问题&#xff0c;则是与网上的大多数解决方案不一样&#xff0c;使…

分类模型为什么使用交叉熵作为损失函数

推导过程 让推理更有体感&#xff0c;进行下面假设&#xff1a; 假设要对猫、狗进行图片识别分类假设模型输出 y y y&#xff0c;是一个几率&#xff0c;表示是猫的概率 训练资料如下&#xff1a; x n x^n xn类别 y ^ n \widehat{y}^n y ​n x 1 x^1 x1猫1 x 2 x^2 x2猫1 x …

【AUTOSAR 基础软件】软件组件的建立与使用(“代理”SWC)

基础软件往往需要建立一些“代理”SWC来完成一些驱动的抽象工作&#xff08;Complex_Device_Driver_Sw或者Ecu_Abstraction_Sw等&#xff09;&#xff0c;或建立Application Sw Component来补齐基础软件需要提供的功能实现。当面对具体的项目时&#xff0c;基础软件开发人员还可…