int.TryParse非預期執行引發的思考


來源:https://blog.guoqianfan.com/2018/11/18/thinking-in-int-TryParse/

問題出現

這天在寫一個頁面,想謹慎些就用了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關鍵字,他們之間的區別是什么呢?

額,這個稍后我會再寫一篇博文的,到時候此處會貼上鏈接,敬請期待...

參考

  1. SF:https://stackoverflow.com/questions/1078512/why-does-integer-tryparse-set-result-to-zero-on-failure?noredirect=1&lq=1
  2. SF:https://stackoverflow.com/questions/10693231/elegant-tryparse
  3. MSDN:Int32.TryParse Method


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM