zoukankan      html  css  js  c++  java
  • 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的思路自己实现。

     

     

     

  • 相关阅读:
    HTML CSS整理笔记
    2020软件工程最后一次作业
    form表单的基本用法
    图片预加载和懒加载(2)——懒加载
    ES6——promise基础
    图片预加载和懒加载(2)——预加载
    图片预加载和懒加载(1)
    js时间——转换为我们需要的格式
    原生js瀑布流
    富文本——小程序中使用特殊符号及标签
  • 原文地址:https://www.cnblogs.com/FudgeBear/p/9527057.html
Copyright © 2011-2022 走看看