C#_Switch语句的内部实现
Switch的C#内部实现
https://www.cnblogs.com/Interkey/p/3730432.html
在IL汇编语言中的Switch指令 -- 按照标号来进行跳转(和goto语句中的标号相同)
执行IL中Switch指令时,从运算栈顶弹出一个无符号整数,然后跳转到整数对应的标号位置继续执行
如果整数值没有对应的标号,则忽略switch指令,调到switch指令之后的一条指令开始执行。
详细分析:
-- 结论 (实验过程见原网页)
1. 整数参数的Switch语句
1a. 连续的整数
c#的switch的case语句对应IL的switch指令中的case子句
1b. 不连续的但是相近的整数
c#的switch的case语句对应IL的switch指令中的case子句,
但是对于case指令之间的"缝隙"整数,会自动跳转default子句的地址
1c. 很不连续的整数
如果按1b的思路,缝隙很大的话,IL中switch指令会凭空增加很多指向default子句指向地址的case子句
编译器不使用switch指令,而是使用了beq指令 -- 取值若相等则跳转到目标位置,否则继续下一个取值
2. 枚举类型的Switch语句
与对待整数没有差别,因为枚举值就是按照整数对待的;如果枚举成员的取值不连续,则对应1b或1c
3. string类型的Switch语句
3a. case子句数量<=4时
string是引用类型参数
同样在IL中没有使用switch指令
如果参数为null的话,则执行流程直接跳转到case null的指令块中
否则,比较参数与case语句对应string的相等性(==),若相等,则跳转到对应的地址后,跳出switch
-- 这就相当于被编译成了一连串的if语句
那么,当case子句过多时,岂不是会导致程序变慢?
3b. case子句数量>4时
如果不是null的话,则会实例化一个字典泛型类 System.Collections.Generic.Dictionary`2<string,int32>
将分别出现在case子句中的string作为key插入到字典中,每个key的value分别对应从0开始的整数(switch子句的序号)
调用字典的TryGetValue()尝试从字典中找到string参数所对应的字典元素
如果在字典中没找到,则跳转到default子句对应的位置
如果找到了,这里出现了switch指令,根据从字典中取到的value整数值,进行switch子句的跳转
switch之后的一条指令则为一个无条件跳转,直接跳转到default子句
这里是当switch指令在栈顶取到的整数值比switch指令中跳转地址数量要大时,忽略switch直接执行之后的指令
总结:
3b情况下,由于Dictionary<TKey,TValue>类型通过key来取值的时间复杂度接近于O(1) -- 有助于提高效率
为了微乎其微的效率提升
1. 尽量在switch中使用连续的取值
2. 如果取值不连续,则使用尽量少的case子句,并将会出现频率高的case放在前面(与if...else if...else类似)
3. 如果使用了大量if语句来判断一个字符串对象是否具有某值,改用Switch
4. 有其他引用类型对象想要使用switch判断但又不能使用时,可以按照3b的思路自己实现。
C#_Switch语句的内部实现的更多相关文章
- 当程序执行一条查询语句时,MySQL内部到底发生了什么? (说一下 MySQL 执行一条查询语句的内部执行过程?
先来个最基本的总结阐述,希望各位小伙伴认真的读一下,哈哈: 1)客户端(运行程序)先通过连接器连接到MySql服务器. 2)连接器通过数据库权限身份验证后,会先查询数据库缓存是否存在(之前执行过相同条 ...
- 【BigData】Java基础_switch语句
语法 switch(表达式) { case x: // 代码块 break; case y: // 代码块 break; default: // 代码块 } switch语句是这样工作的: switc ...
- C#_switch语句,for循环,do while循环,while循环
1:switch语句,代码如下: using System; using System.Collections.Generic; using System.Linq; using System.Tex ...
- C++_系列自学课程_第_12_课_语句_《C++ Primer 第四版》
前面的文章说完了表达式和类型转换的部分内容,在我参考的书里面,接下来讨论的是各种语句,包括:顺序语句.声明语句.复合语句(块语句).语句作用域 .if语句.while语句.for语句.do...whi ...
- 详解Python中的循环语句的用法
一.简介 Python的条件和循环语句,决定了程序的控制流程,体现结构的多样性.须重要理解,if.while.for以及与它们相搭配的 else. elif.break.continue和pass语句 ...
- MyBatis学习(二)、SQL语句映射文件(2)增删改查、参数、缓存
二.SQL语句映射文件(2)增删改查.参数.缓存 2.2 select 一个select 元素非常简单.例如: <!-- 查询学生,根据id --> <select id=" ...
- 关于使用READ TABLE语句的几点注意事项
原文地址 http://www.dlsap.com/thread-34-1-1.html 1. 如果使用READ TABLE语句来读取内部表数据,而不是简单看返回值判断是否存在,那么在使用REA ...
- SQL 操作语句
SQL Server T-SQL高级查询 高级查询在数据库中用得是最频繁的,也是应用最广泛的. Ø 基本常用查询 --select select * from student; --all 查询所有 ...
- 二、SQL语句映射文件(2)增删改查、参数、缓存
//备注:该博客引自:http://limingnihao.iteye.com/blog/106076 2.2 select 一个select 元素非常简单.例如: Xml代码 收藏代码 <!- ...
随机推荐
- pyspark视频
在一个网课上买了一个pyspark视频,贼贵,本来是想把视频解压密码记下来分享出来的,可是其实用的是EVPLAYER,一机一码,一共只有3个激活码 这里我分享视频链接,百度网盘: https://pa ...
- Weblogic web应用中获取文件的绝对路径
注意点: 1. file必须在/下,或者/WEB-INF/,不能在classes下 2. weblogic中进行如下配置,以获取绝对路径: <wls:container-descriptor&g ...
- Zookeeper ZAB 协议分析[转]
写在开始:这是我找到一篇比较好的博客,转载到这来进行备份原文参考: Zookeeper ZAB 协议分析 前言 ZAB 协议是为分布式协调服务 ZooKeeper 专门设计的一种支持崩溃恢复的原子广播 ...
- virtualbox迁移已建虚机存储磁盘方法
1. 先关闭虚拟机 2. 将虚拟机的磁盘拷贝或移动到想要存储的位置,virtualbox一般为.vdi文件(虚拟磁盘文件) 3. vboxmanage internalcommands sethduu ...
- node.js学习之post文件上传 (multer中间件)
express为了性能考虑,采用按需加载的方式,引入各种中间件来完成需求, 平时解析post上传的数据时,是用body-parser. 但这个中间件有缺点,只能解析post的文本内容,(applica ...
- 【vue】本地开发mock数据支持
项目离不开数据渲染的支持,为本地开发配置 数据 支持. (一)方式一:安装JSON Server搭建mock数据的服务器 json Server 是一个创建 伪RESTful服务器的工具. 配置流程 ...
- 三层架构搭建(asp.net mvc + ef)
第一次写博客,想了半天先从简单的三层架构开始吧,希望能帮助到你! 简单介绍一下三层架构, 三层架构从上到下分:表现层(UI),业务逻辑层(BLL),数据访问层(DAL)再加上数据模型(Model),用 ...
- 01_Docker概念简介、组件介绍、使用场景和命名空间
一.简介 Docker是一个能够把开发的应用程序自动部署到容器的开源引擎.Docker在虚拟化的容器执行环境中增加了一个应用程序部署引擎.该引擎的目标就是提供一个轻量.快速的环境,能够运行开发者的程序 ...
- CO借贷标识及转换
前台提前数据源0CO_PC_01的数据时发现借贷方有O.C.S.D.不是传统的FI借贷标识(S = 借记,H = 贷记). 由"D"指出贷方记帐.从以下项中发生这些记帐 财务会计中 ...
- Linux磁盘与文件系统管理(二)
fsck 检查并修复文件系统中的错误,即针对有问题的系统或磁盘进行修复,类似的命令还有e2fsck,修复前有以下要求: 1)文件系统必须是卸载状态 2)不要对正常的分区使用fsck,不加参数的情况下, ...