坊間程式書籍介紹C# switch時,大部分都說是if else的延伸。例如:
//程式片段A
int foo=某數;
if(foo==1)
{
Console.WriteLine("A");
}
else if(foo==2)
{
Console.WriteLine("B");
}
else if(foo==3)
{
Console.WriteLine("C");
}
else
{
Console.WriteLine("not matchs");
}
//程式片段B
int foo=某數;
switch (foo)
{
case 1:
Console.WriteLine("A");
break;
case 2:
Console.WriteLine("B");
break;
case 3:
Console.WriteLine("C");
break;
default:
Console.WriteLine("not matchs");
break;
}
程式片段A和程式片段B執行結果是一樣的。但是再看看下面的
//程式片段C
string str= "";
if(typeof(bool) == str.GetType()))
{
Console.WriteLine("is bool");
}
else if(typeof(string) == str.GetType()))
{
Console.WriteLine("is string");
}
else
{
Console.WriteLine("not matchs");
}
//程式片段D
string str= "";
switch(str.GetType())
{
case typeof(bool):
Console.WriteLine("is bool");
break;
case typeof(string):
Console.WriteLine("is string");
break;
default:
Console.WriteLine("not matchs");
break;
}
程式片段C能改寫成程式片段D嗎?
答案是不行:
因為
CIL在轉換switch時並不"一定"以if else形式轉換,多數情況下是產生一個case資料組成的jump table後,從jump table搜尋條件符合後執行對應記憶體位址的程式。這樣做是為了效能考量;
CIL會依據case資料的連續度和多寡來決定以哪種方式轉換。因為可能轉換成jump table,所以case資料必然是(常數)constant組成。例如以下程式就可以執行:
//程式片段E
public static class ActionStatus
{
public const string Create = "A";
public const string Edit = "E";
public const string Delete = "D";
public const string Search = "S";
}
string str= "A";
switch(str)
{
case ActionStatus.Search:
Console.WriteLine("do not change db data");
break;
default:
Console.WriteLine("will change db data");
break;
}