關(guān)于C# if語(yǔ)句中并列條件的執(zhí)行
更新時(shí)間:2012年02月24日 14:11:52 作者:
我們知道,當(dāng)兩個(gè)條件進(jìn)行邏輯與操作的時(shí)候,其中任何一個(gè)條件為假,則表達(dá)式的結(jié)果為假。所以,遇到(A 且 B)這種表達(dá)式,如果A為假的話,B是不是真假都無(wú)所謂了,當(dāng)遇到一個(gè)假條件的時(shí)候,程序也就沒(méi)有必要去額外的判斷剩下的東西了
C#語(yǔ)言中也是如此。當(dāng)多個(gè)條件進(jìn)行邏輯與操作的時(shí)候,判定會(huì)從表達(dá)式左邊執(zhí)行到右邊,遇到任何一個(gè)為假,后面就都不做了。這很聰明,然而如果后面的條件會(huì)拋出異常,就是個(gè)潛在的問(wèn)題。一旦之前的條件為真,就會(huì)繼續(xù)執(zhí)行,執(zhí)行到拋出異常的條件時(shí),程序就爆了,哈哈。
我們可以寫(xiě)個(gè)簡(jiǎn)單的demo試試。下面的這段代碼是坑爹的,之后我會(huì)說(shuō)明原因,但大家可以先從直觀的層面上理解一下,最后我會(huì)給出正確的測(cè)試方法。
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();
}
這段代碼乍看沒(méi)問(wèn)題,并且在運(yùn)行時(shí)也給出了我們期望的結(jié)果,即第一段語(yǔ)句輸出Shit,不拋出異常(當(dāng)前面為false,后面會(huì)拋異常的ds.Tables[0].Rows.Count > 0就不做),而第二段語(yǔ)句因?yàn)橹笆莟rue,所以要執(zhí)行對(duì)dataset的判斷,所以拋出異常。但如果用reflector反編譯程序集,就會(huì)發(fā)現(xiàn),編譯器已經(jīng)把上面的代碼優(yōu)化成了下面這種形式,我們的if語(yǔ)句中寫(xiě)死的true和false已經(jīng)被閹割掉了,所以并不能說(shuō)明if語(yǔ)句執(zhí)行的問(wèn)題。
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();
}
其實(shí),如果你仔細(xì)觀察,在輸入這段代碼的過(guò)程中,VS就已經(jīng)提示if (false && ds.Tables[0].Rows.Count > 0)中,后者是不可達(dá)的。這是即時(shí)編譯的效果。既然即時(shí)編譯說(shuō)后面的代碼不可達(dá),就意味著不可達(dá)的代碼會(huì)在編譯期被切掉。因此,剛才我們?cè)谏厦婵吹降木幾g結(jié)果也就是自然的事情了。
同樣,如果你直接把1 == 0, 1 == 1這樣的條件拼上去的話,編譯器也會(huì)發(fā)現(xiàn)的。所以我們要找一種不會(huì)被編譯器發(fā)現(xiàn)的寫(xiě)法,要讓我們的條件判定代碼只能在運(yùn)行時(shí)執(zhí)行,而不是編譯時(shí)被調(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();
}
我們?cè)賮?lái)執(zhí)行,發(fā)現(xiàn)這次的結(jié)果是真正意義的滿足了我們的目的,說(shuō)明了當(dāng)多個(gè)條件進(jìn)行邏輯與的時(shí)候,C#的執(zhí)行機(jī)制:
在or關(guān)系中,只要有一個(gè)true,整個(gè)表達(dá)式就是true了。但如果你讓可能引發(fā)異常的語(yǔ)句先于之后會(huì)返回true的語(yǔ)句執(zhí)行,就會(huì)爆。
比如這樣寫(xiě)的話會(huì)爆,因?yàn)榕袛郘ength的前提是得有個(gè)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打開(kāi)mscorlib中的System.String找到~
我們可以寫(xiě)個(gè)簡(jiǎn)單的demo試試。下面的這段代碼是坑爹的,之后我會(huì)說(shuō)明原因,但大家可以先從直觀的層面上理解一下,最后我會(huì)給出正確的測(cè)試方法。
復(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();
}
這段代碼乍看沒(méi)問(wèn)題,并且在運(yùn)行時(shí)也給出了我們期望的結(jié)果,即第一段語(yǔ)句輸出Shit,不拋出異常(當(dāng)前面為false,后面會(huì)拋異常的ds.Tables[0].Rows.Count > 0就不做),而第二段語(yǔ)句因?yàn)橹笆莟rue,所以要執(zhí)行對(duì)dataset的判斷,所以拋出異常。但如果用reflector反編譯程序集,就會(huì)發(fā)現(xiàn),編譯器已經(jīng)把上面的代碼優(yōu)化成了下面這種形式,我們的if語(yǔ)句中寫(xiě)死的true和false已經(jīng)被閹割掉了,所以并不能說(shuō)明if語(yǔ)句執(zhí)行的問(wèn)題。
復(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();
}
其實(shí),如果你仔細(xì)觀察,在輸入這段代碼的過(guò)程中,VS就已經(jīng)提示if (false && ds.Tables[0].Rows.Count > 0)中,后者是不可達(dá)的。這是即時(shí)編譯的效果。既然即時(shí)編譯說(shuō)后面的代碼不可達(dá),就意味著不可達(dá)的代碼會(huì)在編譯期被切掉。因此,剛才我們?cè)谏厦婵吹降木幾g結(jié)果也就是自然的事情了。
同樣,如果你直接把1 == 0, 1 == 1這樣的條件拼上去的話,編譯器也會(huì)發(fā)現(xiàn)的。所以我們要找一種不會(huì)被編譯器發(fā)現(xiàn)的寫(xiě)法,要讓我們的條件判定代碼只能在運(yùn)行時(shí)執(zhí)行,而不是編譯時(shí)被調(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();
}
我們?cè)賮?lái)執(zhí)行,發(fā)現(xiàn)這次的結(jié)果是真正意義的滿足了我們的目的,說(shuō)明了當(dāng)多個(gè)條件進(jìn)行邏輯與的時(shí)候,C#的執(zhí)行機(jī)制:
在or關(guān)系中,只要有一個(gè)true,整個(gè)表達(dá)式就是true了。但如果你讓可能引發(fā)異常的語(yǔ)句先于之后會(huì)返回true的語(yǔ)句執(zhí)行,就會(huì)爆。
比如這樣寫(xiě)的話會(huì)爆,因?yàn)榕袛郘ength的前提是得有個(gè)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打開(kāi)mscorlib中的System.String找到~
相關(guān)文章
asp.net core多文件分塊同時(shí)上傳組件使用詳解
這篇文章主要為大家介紹了一個(gè)可多個(gè)文件同時(shí)上傳、斷點(diǎn)續(xù)傳,并實(shí)時(shí)反饋上傳進(jìn)度的 Asp.Net core 組件,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12
System.Runtime.InteropServices.COMException的解決方法
完美解決“換另一臺(tái)電腦上用VS2008繼續(xù)開(kāi)發(fā)web項(xiàng)目時(shí)出現(xiàn)“System.Runtime.InteropServices.COMException”,然后是加載不了項(xiàng)目?!?2009-03-03
.net core使用redis基于StackExchange.Redis
這篇文章主要為大家詳細(xì)介紹了.net core使用redis基于StackExchange.Redis的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-04-04
asp.net基于JWT的web api身份驗(yàn)證及跨域調(diào)用實(shí)踐
這篇文章主要介紹了asp.net基于JWT的web api身份驗(yàn)證及跨域調(diào)用實(shí)踐,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-07-07
在dropDownList中實(shí)現(xiàn)既能輸入一個(gè)新值又能實(shí)現(xiàn)下拉選的代碼
在dropDownList中實(shí)現(xiàn)既能輸入一個(gè)新值,又能實(shí)現(xiàn)下拉選項(xiàng),想必很多的朋友已經(jīng)為此功能按耐不住了吧,接下來(lái)與大家分享下如何實(shí)現(xiàn),感興趣的朋友可以參考下哈2013-04-04

