關(guān)于C# if語句中并列條件的執(zhí)行
更新時間:2012年02月24日 14:11:52 作者:
我們知道,當(dāng)兩個條件進(jìn)行邏輯與操作的時候,其中任何一個條件為假,則表達(dá)式的結(jié)果為假。所以,遇到(A 且 B)這種表達(dá)式,如果A為假的話,B是不是真假都無所謂了,當(dāng)遇到一個假條件的時候,程序也就沒有必要去額外的判斷剩下的東西了
C#語言中也是如此。當(dāng)多個條件進(jìn)行邏輯與操作的時候,判定會從表達(dá)式左邊執(zhí)行到右邊,遇到任何一個為假,后面就都不做了。這很聰明,然而如果后面的條件會拋出異常,就是個潛在的問題。一旦之前的條件為真,就會繼續(xù)執(zhí)行,執(zhí)行到拋出異常的條件時,程序就爆了,哈哈。
我們可以寫個簡單的demo試試。下面的這段代碼是坑爹的,之后我會說明原因,但大家可以先從直觀的層面上理解一下,最后我會給出正確的測試方法。
static void Main(string[] args)
{
DataSet ds = null;
if (false && ds.Tables[0].Rows.Count > 0)
{
Console.WriteLine("Fuck");
}
else
{
Console.WriteLine("Shit");
}
if (true && ds.Tables[0].Rows.Count > 0)
{
Console.WriteLine("WOW");
}
else
{
Console.WriteLine("KAO");
}
Console.ReadKey();
}
這段代碼乍看沒問題,并且在運(yùn)行時也給出了我們期望的結(jié)果,即第一段語句輸出Shit,不拋出異常(當(dāng)前面為false,后面會拋異常的ds.Tables[0].Rows.Count > 0就不做),而第二段語句因為之前是true,所以要執(zhí)行對dataset的判斷,所以拋出異常。但如果用reflector反編譯程序集,就會發(fā)現(xiàn),編譯器已經(jīng)把上面的代碼優(yōu)化成了下面這種形式,我們的if語句中寫死的true和false已經(jīng)被閹割掉了,所以并不能說明if語句執(zhí)行的問題。
private static void Main(string[] args)
{
DataSet ds = null;
Console.WriteLine("Shit");
if (ds.Tables[0].Rows.Count > 0)
{
Console.WriteLine("WOW");
}
else
{
Console.WriteLine("KAO");
}
Console.ReadKey();
}
其實,如果你仔細(xì)觀察,在輸入這段代碼的過程中,VS就已經(jīng)提示if (false && ds.Tables[0].Rows.Count > 0)中,后者是不可達(dá)的。這是即時編譯的效果。既然即時編譯說后面的代碼不可達(dá),就意味著不可達(dá)的代碼會在編譯期被切掉。因此,剛才我們在上面看到的編譯結(jié)果也就是自然的事情了。
同樣,如果你直接把1 == 0, 1 == 1這樣的條件拼上去的話,編譯器也會發(fā)現(xiàn)的。所以我們要找一種不會被編譯器發(fā)現(xiàn)的寫法,要讓我們的條件判定代碼只能在運(yùn)行時執(zhí)行,而不是編譯時被調(diào)整。比如下面這種:
static void Main(string[] args)
{
DataSet ds = null;
int i = 0;
int j = 1;
if (i + j == 0 && ds.Tables[0].Rows.Count > 0)
{
Console.WriteLine("Fuck");
}
else
{
Console.WriteLine("Shit");
}
if (i + j == 1 && ds.Tables[0].Rows.Count > 0)
{
Console.WriteLine("WOW");
}
else
{
Console.WriteLine("KAO");
}
Console.ReadKey();
}
我們再來執(zhí)行,發(fā)現(xiàn)這次的結(jié)果是真正意義的滿足了我們的目的,說明了當(dāng)多個條件進(jìn)行邏輯與的時候,C#的執(zhí)行機(jī)制:
在or關(guān)系中,只要有一個true,整個表達(dá)式就是true了。但如果你讓可能引發(fā)異常的語句先于之后會返回true的語句執(zhí)行,就會爆。
比如這樣寫的話會爆,因為判斷Length的前提是得有個string:
public static bool IsNullOrEmpty(string str)
{
if (str.Length == 0 || str == null)
{
return true;
}
return false;
}
public static bool IsNullOrEmpty(string str)
{
if (str == null || str.Length == 0)
{
return true;
}
return false;
}
public static bool IsNullOrEmpty(string value)
{
if (value != null)
{
return (value.Length == 0);
}
return true;
}
上面這段代碼可以用reflector打開mscorlib中的System.String找到~
我們可以寫個簡單的demo試試。下面的這段代碼是坑爹的,之后我會說明原因,但大家可以先從直觀的層面上理解一下,最后我會給出正確的測試方法。
復(fù)制代碼 代碼如下:
static void Main(string[] args)
{
DataSet ds = null;
if (false && ds.Tables[0].Rows.Count > 0)
{
Console.WriteLine("Fuck");
}
else
{
Console.WriteLine("Shit");
}
if (true && ds.Tables[0].Rows.Count > 0)
{
Console.WriteLine("WOW");
}
else
{
Console.WriteLine("KAO");
}
Console.ReadKey();
}
這段代碼乍看沒問題,并且在運(yùn)行時也給出了我們期望的結(jié)果,即第一段語句輸出Shit,不拋出異常(當(dāng)前面為false,后面會拋異常的ds.Tables[0].Rows.Count > 0就不做),而第二段語句因為之前是true,所以要執(zhí)行對dataset的判斷,所以拋出異常。但如果用reflector反編譯程序集,就會發(fā)現(xiàn),編譯器已經(jīng)把上面的代碼優(yōu)化成了下面這種形式,我們的if語句中寫死的true和false已經(jīng)被閹割掉了,所以并不能說明if語句執(zhí)行的問題。
復(fù)制代碼 代碼如下:
private static void Main(string[] args)
{
DataSet ds = null;
Console.WriteLine("Shit");
if (ds.Tables[0].Rows.Count > 0)
{
Console.WriteLine("WOW");
}
else
{
Console.WriteLine("KAO");
}
Console.ReadKey();
}
其實,如果你仔細(xì)觀察,在輸入這段代碼的過程中,VS就已經(jīng)提示if (false && ds.Tables[0].Rows.Count > 0)中,后者是不可達(dá)的。這是即時編譯的效果。既然即時編譯說后面的代碼不可達(dá),就意味著不可達(dá)的代碼會在編譯期被切掉。因此,剛才我們在上面看到的編譯結(jié)果也就是自然的事情了。
同樣,如果你直接把1 == 0, 1 == 1這樣的條件拼上去的話,編譯器也會發(fā)現(xiàn)的。所以我們要找一種不會被編譯器發(fā)現(xiàn)的寫法,要讓我們的條件判定代碼只能在運(yùn)行時執(zhí)行,而不是編譯時被調(diào)整。比如下面這種:
復(fù)制代碼 代碼如下:
static void Main(string[] args)
{
DataSet ds = null;
int i = 0;
int j = 1;
if (i + j == 0 && ds.Tables[0].Rows.Count > 0)
{
Console.WriteLine("Fuck");
}
else
{
Console.WriteLine("Shit");
}
if (i + j == 1 && ds.Tables[0].Rows.Count > 0)
{
Console.WriteLine("WOW");
}
else
{
Console.WriteLine("KAO");
}
Console.ReadKey();
}
我們再來執(zhí)行,發(fā)現(xiàn)這次的結(jié)果是真正意義的滿足了我們的目的,說明了當(dāng)多個條件進(jìn)行邏輯與的時候,C#的執(zhí)行機(jī)制:
在or關(guān)系中,只要有一個true,整個表達(dá)式就是true了。但如果你讓可能引發(fā)異常的語句先于之后會返回true的語句執(zhí)行,就會爆。
比如這樣寫的話會爆,因為判斷Length的前提是得有個string:
復(fù)制代碼 代碼如下:
public static bool IsNullOrEmpty(string str)
{
if (str.Length == 0 || str == null)
{
return true;
}
return false;
}
復(fù)制代碼 代碼如下:
public static bool IsNullOrEmpty(string str)
{
if (str == null || str.Length == 0)
{
return true;
}
return false;
}
復(fù)制代碼 代碼如下:
public static bool IsNullOrEmpty(string value)
{
if (value != null)
{
return (value.Length == 0);
}
return true;
}
上面這段代碼可以用reflector打開mscorlib中的System.String找到~
相關(guān)文章
C#(.NET)數(shù)據(jù)訪問連接、查詢、插入等操作的封裝類
一個C#(.NET)數(shù)據(jù)訪問連接、查詢、插入等操作的封裝類2008-05-05在應(yīng)用程序級別之外使用注冊為allowDefinition=''MachineToApplication''的節(jié)是錯誤的
在應(yīng)用程序級別之外使用注冊為 allowDefinition='MachineToApplication' 的節(jié)是錯誤的2009-03-03repeater隔行換色與鼠標(biāo)停留在上面達(dá)到變色效果
鼠標(biāo)停留在上面是變成其他的顏色,很多新手朋友都想實現(xiàn)這種效果,可是無從下手,本文整理了一些解決技巧,感興趣的朋友可以參考下啊2013-01-01asp.net Repeater顯示父子表數(shù)據(jù),無閃爍
兩天在改項目bug,發(fā)現(xiàn)以前有人做的repeater顯示父子表結(jié)構(gòu)展開和關(guān)閉子表數(shù)據(jù)時總是有閃爍,于是就試著改成無閃爍的,成功了,與大家分享.2009-12-12