为了账号安全,请及时绑定邮箱和手机立即绑定

为什么编译器会在 switch 中添加语句?

为什么编译器会在 switch 中添加语句?

C#
BIG阳 2022-06-18 17:37:51
我有以下相当简单的 switch 语句。// 较早的字符串 fullPath = GetFullPath(); 字符串类型 = GetEntityType();switch (type.ToLower()) {    case "tables":        tables.Add(fullPath);        break;    case "views":        views.Add(fullPath);        break;    case "functions":        functions.Add(fullPath);        break;    case "storedprocs":        storedprocs.Add(fullPath);        break;    case "data":        data.Add(fullPath);        break;    case "layouts":        layouts.Add(fullPath);        break;    case "scripts":        scripts.Add(fullPath);        break;    default:        Console.WriteLine($"What is this: {type}");        break;}当我使用 Reflector 反编译生成的二进制文件时,switch(string)它已更改为 ComputeStringHash,然后在每个 case 语句中,它通过if语句检查值。听起来它正在做双倍的工作。    string s = str2.ToLower();    switch (<PrivateImplementationDetails>.ComputeStringHash(s))    {        case 0x20890fc4:            if (s == "tables")            {                break;            }            goto Label_0218;        case 0x454a414e:            if (s == "functions")            {                goto Label_01DE;            }            goto Label_0218;        case 0x4facf6d1:            if (s == "views")            {                goto Label_01D3;            }            goto Label_0218;        case 0xcdfe2cb3:            if (s == "storedprocs")            {                goto Label_01E9;            }            goto Label_0218;        case 0xd872e2a5:            if (s == "data")            {                goto Label_01F4;            }            goto Label_0218;        case 0x9b4a129b:            if (s == "scripts")            {                goto Label_020C;            }            goto Label_0218;        case 0xba971064:            if (s == "layouts")            {                goto Label_0200;            }            goto Label_0218;        default:            goto Label_0218;    }
查看完整描述

1 回答

?
九州编程

TA贡献1785条经验 获得超4个赞

这是一个非常聪明的优化,它可以让几乎独立于语句块中的switch字符串数量的时间来完成它的工作。case

这种优化是基于观察到相同字符串的哈希码必须相同。编译器不是逐个检查字符串是否相等,而是计算一次目标字符串的哈希,并在 O(1) 中执行基于表的查找。这使编译器达到所需的情况,此时编译器需要检查字符串是否实际相等。

请注意,当多个查找字符串具有相同的哈希码时,会出现一些罕见的情况。在这种情况下,生成的case语句将包含多个if以在具有相同哈希码的字符串中做出决定。

总的来说,这种行为模仿了基于散列的字典的行为:散列码确定case(相当于散列桶),而里面的一系列ifs 确定是否存在匹配。这会带来更好的性能,因为它可以让编译器跳过不必要的检查。


查看完整回答
反对 回复 2022-06-18
  • 1 回答
  • 0 关注
  • 149 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信