我有以下相当简单的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;
}
first.Add(fullPath);
continue;
Label_01D3:
second.Add(fullPath);
continue;
Label_01DE:
list3.Add(fullPath);
continue;
Label_01E9:
list4.Add(fullPath);
continue;
Label_01F4:
list5.Add(fullPath);
continue;
Label_0200:
list6.Add(fullPath);
continue;
Label_020C:
list7.Add(fullPath);
continue;
Label_0218:
Console.WriteLine("What is this: " + str2);
}
答案 0 :(得分:7)
这是一个非常聪明的优化,它使switch
能够及时完成工作,而该工作几乎与语句的case
块中的字符串数无关。
此优化基于以下观察结果:相同字符串的哈希码必须相同。编译器没有一次检查字符串是否相等,而是只计算一次目标字符串的哈希,然后在O(1)中执行基于表的查找。这样可以使编译器达到所需的情况,此时编译器需要检查字符串实际上是否相等。
请注意,在某些情况下,多个查询字符串具有相同的哈希码。在这种情况下,生成的case
语句将包含多个if
,以便在具有相等哈希码的字符串之间进行决定。
总体而言,此行为模仿了基于哈希的字典的行为:哈希代码确定case
(相当于哈希桶),内部的一系列if
确定是否存在匹配项。这样可以提高性能,因为它可以使编译器跳过不必要的检查。