|
|
1
115
重要的是不要将C#switch语句与CIL switch指令混淆。 CIL开关是一个跳转表,它需要一组跳转地址的索引。 这仅在C#开关的外壳相邻时有用:
但如果它们不是:
(您需要一个大约3000个条目大小的表,仅使用3个插槽)
对于较大的非相邻表达式集,编译器可能从二叉树搜索开始,最后是if-else-if-else最后几项。 对于包含相邻项束的表达式集,编译器可以进行二叉树搜索,最后是CIL开关。 这充满了“可能”&“可能”,它取决于编译器(可能与Mono或Rotor不同)。
然后我还使用了非相邻大小写表达式:
有趣的是,二叉树搜索似乎比CIL开关指令快一点(可能不是统计上的)。 布莱恩,你用过这个词“ “,从计算复杂性理论的角度来看,它有一个非常明确的含义。虽然简化的相邻整数示例可能产生被认为是O(1)(常数)的CIL,但稀疏示例是O(对数n)(对数),聚集示例介于两者之间,小示例是O(n)(线性)。
这甚至不能解决字符串的情况,在这种情况下
如果你查一下 C# Language Specification (不是CIL规范) 归根结底,在现代系统中,对整数表达式进行C#切换是一种亚微秒级的操作,通常不值得担心。 当然,这些时间将取决于机器和条件。我不会注意这些计时测试,我们所说的微秒持续时间与正在运行的任何实际代码(必须包含一些实际代码,否则编译器将优化分支)或系统中的抖动相比都是微不足道的。我的答案是基于使用 IL DASM 检查由C#编译器创建的CIL。当然,这不是最终的,因为CPU运行的实际指令随后由JIT创建。 我已经检查了x86机器上实际执行的最终CPU指令,可以确认一个简单的相邻设置开关执行以下操作:
|
|
|
2
103
这是我最初的帖子,引发了一些争论。。。 因为这是错误的 :
不 在某些情况下,编译器将使用CIL switch语句,该语句实际上是使用跳转表的常量时间分支。然而,正如 Ivan Hamilton 编译器可能会完全生成其他内容。
|
|
|
3
23
我想到的第一个原因是 历史的
另一个更合理的原因是 语言复杂性会增加 :
首先,应该将对象与对象进行比较吗
此外,允许打开对象将 打破关于switch语句的基本假设 . 如果允许打开对象,编译器将无法强制执行两条规则来管理switch语句(请参阅 C# version 3.0 language specification , §8.7.2):
在假设的情况下考虑这个代码示例,允许非常量的情况值:
代码将做什么?如果case语句被重新排序呢?事实上,C#使switch失败为非法的原因之一是switch语句可以任意重新排列。 这些规则的存在是有原因的——因此程序员可以通过查看一个case块,确定输入块的确切条件。当前面提到的switch语句增长到100行或更多行时(它将增长),这样的知识是非常宝贵的。 |
|
|
4
10
|
|
|
5
10
编译器可以(并且确实)选择:
switch语句不是常量时间分支。编译器可能会找到捷径(使用散列桶等),但更复杂的情况会生成更复杂的MSIL代码,有些情况会比其他情况更早分支。 为了处理字符串大小写,编译器最终将使用a.Equals(b)(可能还有a.GetHashCode())。我认为编译器使用任何满足这些约束的对象都是很繁琐的。 至于对静态大小写表达式的需要。。。如果case表达式不是确定性的,那么其中一些优化(散列、缓存等)将不可用。但是我们已经看到,有时候编译器只是选择了简单的if-else-if-else道路。。。 编辑: lomaxx -您对“typeof”运算符的理解不正确。“typeof”操作符用于获取类型的System.Type对象(与其超类型或接口无关)。检查对象与给定类型的运行时兼容性是“is”操作符的工作。这里使用“typeof”来表示对象是不相关的。 |
|
|
6
7
现在使用C#7,您可以:
|
|
|
7
6
根据杰夫·阿特伍德的说法, the switch statement is a programming atrocity . 少用。
|
|
8
6
没错,没有 有 事实上,许多语言都使用动态开关语句。然而,这意味着重新排列“case”子句可以改变代码的行为。 Why is the C# switch statement designed to not allow fall-through, but still require a break? 允许动态大小写表达式可能导致以下PHP代码:
坦白地说,应该使用
|
|
|
9
3
|
|
10
3
上面犹大的回答给了我一个想法。您可以在上面使用
这允许您将行为与switch语句样式相同的类型相关联。我相信它还有一个额外的好处,那就是在编译到IL时,它是键控的,而不是开关式的跳转表。 |
|
|
11
0
但这并没有什么好处。 整数类型的case语句允许编译器进行大量优化:
|
|
|
12
0
根据
the switch statement documentation
|
|
|
13
0
因为语言允许 一串 要在switch语句中使用的类型我假定编译器无法为该类型的常量时间分支实现生成代码,并且需要生成if-then样式。
我在C#和.NET方面没有太多的经验,但似乎语言设计者不允许静态访问类型系统,除非在狭窄的环境中。这个 类型 |
|
|
14
0
另一个选择是,对于可以使用数字和字符串的类型,没有顺序。因此,类型开关不能构建二进制搜索树,只能构建线性搜索。 |
|
|
15
0
我同意 this comment 使用表驱动的方法通常更好。 在C#1.0中,这是不可能的,因为它没有泛型和匿名委托。 |
|
|
16
0
|
|
17
0
因此,您会得到:
here . |
|
|
Bunyamin Erkaya · 使用开关输入后立即断开,或者如果 1 年前 |
|
|
Ettapp · switch语句中的类型保护类 1 年前 |
|
|
user23760512 · 所欠所得税的计算不正确 1 年前 |
|
|
Johnml · 将if-else语句转换为Switch语句 1 年前 |
|
Piotr Siupa · 如何在switch语句中使用太空船操作员 1 年前 |
|
|
Sybe · 将输入转换为数字的方法不起作用[重复] 2 年前 |