在C#中做類型轉換時有時會使用到TryParse方法,該方法如果轉換失敗,out參數的值是什麼呢?我就在這裡犯傻了,特意寫文記錄下。 ...
問題出現
這天在寫一個頁面,想謹慎些就用了int.TryParse
,結果出問題了。
代碼如下:
int id = 1000;
//Request.QueryString["id"] = null
int.TryParse( Request.QueryString["id"], out id );
//使用 id 進行其他操作...
因為Request.QueryString["id"] = null
,所以我的預期是id=1000
。可是我錯了,實際結果是id=0。測試多次都是這樣。我感覺要出事了。
事實上我對TryParse一直存在這麼個認知(以上面代碼舉例):
- 如果轉換成功,id=轉換後的值;
- 如果轉換失敗,不進行任何操作,id仍然是1000。
可是現在我知道我錯了,更嚴重的是我按照這樣的思維寫了不少代碼。。。還好我確保輸入正確使其都能轉化成功,至今沒出什麼么蛾子。出么蛾子的話我早就滾蛋了吧。
不過現在不是考慮這些的時候,工作要緊,就趕緊改了代碼,先把新功能上線了再說...
問題分析
幾天後,有空了,就開始研究這個問題,總結如下:
TryParse
轉換失敗時,out參數
返回的是什麼?
網上搜了下,在stackoverflow上看到了這麼一段話(谷歌翻譯):
你是對的,如果失敗,TryParse使用0。(MSDN非常清楚地說明瞭這一點)但你可以檢查paseSuccess並返回你的預設值,如果這是你想要的。
現在發現當時看的是VB.NET...還好此時此刻這貨特性和C#是一樣的...不然又坑了...
既然提到了MSDN,那就去看看。果然,MSDN上在result
處寫著這麼一段話:
result
Int32
當此方法返回時,如果轉換成功,則包含與s
中所包含的數字等效的 32 位無符號整數值;如果轉換失敗,則包含零。 如果s
參數為null
或為 Empty、格式不正確,或者表示小於 MinValue 或大於 MaxValue 的數,則轉換失敗。 此參數未經初始化即進行傳遞;最初在result
中提供的任何值都會被覆蓋。
有這麼幾處重點:
- 當此方法返回時,如果轉換成功,則包含與
s
中所包含的數字等效的 32 位無符號整數值;如果轉換失敗,則包含零。 - 此參數未經初始化即進行傳遞;最初在
result
中提供的任何值都會被覆蓋。
”out參數“、“未經初始化即進行傳遞”,看到這些,我突然想到了out
參數的特性:“out
參數好像是不需要初始化的“。如果傳入時不需要初始化,那麼在TryParse方法內部,當轉換成功時可以賦值(轉換後的值);當轉換失敗時,也必須賦值,要賦值就必定是預設值。
到此我的疑惑已經解開了。搞了大半天,竟然是out關鍵字
的性質。恍然大悟的同時,又感覺到自己的C#基礎的薄弱。。。
總結
TryParse
使用時,傳入的out
參數的原始值會被覆蓋掉,具體如下:
- 如果轉換成功,使用轉換成功後的值覆蓋
- 如果轉換失敗,使用該類型的預設值覆蓋
其他
轉換失敗時不使用預設值覆蓋原始值的2種方法
既然已經瞭解了本質,當然也不能忘了咱們的初衷,那就是TryParse轉換失敗時,怎麼不使用預設值覆蓋我們設定的原始值?
下麵分享一下在stackoverflow上看到的2種方法
//方法1、使用out參數的性質
int i = int.TryParse(s, out i) ? i : 42;
//方法2、擴展方法
public class Extensions
{
public static int? TryParse(string this Source)
{
if(int.tryparse ....
}
}
//使用
v = "234".TryParse() ?? 0
out
關鍵字和ref
關鍵字的區別
說到out
關鍵字,就不得不提ref
關鍵字,他們之間的區別是什麼呢?
額,這個稍後我會再寫一篇博文的,到時候此處會貼上鏈接,敬請期待...
參考
- SF:https://stackoverflow.com/questions/1078512/why-does-integer-tryparse-set-result-to-zero-on-failure?noredirect=1&lq=1
- SF:https://stackoverflow.com/questions/10693231/elegant-tryparse
- MSDN:Int32.TryParse Method