switch 里面的case 分支是从上往下一个个判断的么
我看了一下中间语言,他是把所有的case的变量集中起来,然后判断是否跟某个变量相等,如果相等,就转到相应的处理
但是这个判断也是从上往下比较是不是和这些变量相等的把,那和if else按顺序判断不是一样的么。
vs里面case加不了断点,f11就直接进入到分支了,但是实际上,是不是从上往下case都判断过呢
------解决方案--------------------我也感觉是这样的,因为中间语言看了好像是这样,只不过是switch形成了一个中间表的样子,但是用那个变量值和表中的值比较的时候 好像也是从上往下比较的吧
=========================================
你要明白什么是hash表,什么是内存寻址 就不会这么认为了。 基址+偏移量。也就是说就算他是生成了一个中间表他一不会去全体扫描,他只会直接算出偏移量,然后直接跳转过去就ok
------解决方案--------------------
------解决方案--------------------
------解决方案--------------------逻辑上是从上向下顺序查找的,楼主钻研的精神可嘉
------解决方案--------------------
------解决方案--------------------还是深了,不赞同lz这样做,但是精神无疑是好的。
如果是我的话,我肯定是先解决吃饭问题,然后在解决吃什么的问题,最后在讨论为什么吃这些东西的问题。
------解决方案--------------------
可以看看stackoverflow上关于这个讨论
http://stackoverflow.com/questions/3366376/are-net-switch-statements-hashed-or-indexed
我说一下我的理解。首先不像C/C++一样,C#的switch除了支持数字,还支持字符串类型。
字符串比较简单,先说字符串,如果case个数较少的话,C#会用if else这样的方式来实现,就像41楼列出来的一样,从前往后一个个比较;如果个数较多的话(我也不知道具体多少算多),C#会new一个Dictionary来实现快速查找,Dictionary基本上就是一个hashtable,把字符串映射到一些连续的数字上(注意,是连续的,这很重要,并不是简单的GetHashCode返回的乱七八糟的数字),然后再switch这个数字。
再说数字的,数字的也要分情况,如果那些case里的数字是离散的,那C#也是会用if else来实现;如果是一串连续的数字,像1,2,3,这时候就会用il里定义的switch指令 ,像这样 switch( IL_0229, IL_0239, IL_0249),这三个行号放在一块叫跳转表(jump table), 这个switch指令的执行我猜是这样的(我没看过il的教程,纯粹是猜测),判断当前寄存器里的值,如果值为0,那么跳转到IL_0229这行,如果值为1,则跳转到IL_0239,2则跳IL_0249。这个动作是O(1)的,不需要一个一个判断。注意这里寄存器里的值是连续的,只能从0往上加,如果你case的第一个不是0,编译器会先做一些四则运算把它变成0,就像1,2,3的话减去1就可以了。 如果你给的case里又有连续又有离散的呢,比方说我有4个值,1,2,3,100,这时候我发现编译器会先if else一下是不是100,如果不是的话剩下那1,2,3又可以switch了,反正这个是考验编译器智商的了,尽可能的优化。
如果你还想问il里的switch到底是怎么实现o(1)的跳转的,可以看一下编译成x86后的代码,类似于这行,
jmp dword ptr [eax*4+002B2878h]
至于vs里f11单步不到中间的判断过程(即使是开启显示汇编),我觉得是vs考虑到大多数人没有想要看那些中间过程,而是想直接知道跳到哪个case了,所以把这个过程有意隐藏了
------解决方案--------------------建议到80X86 微机原理上看看,我以前看到过,好像是跳转的,不是逐条的
------解决方案--------------------mark晚上回去想想。 “47”楼应该接近答案了。