你寫的return null正確嗎?


上次一篇“你寫的try…catch真的有必要嗎”引起了很多朋友的討論。本次我在code review又發現了一個問題,那就是有人有意無意的寫出了return null這樣的代碼,例如:

       public User GetUser(Guid userId)
        {
            if ( /*for some reason*/)
                return null;
            
            return DB.GetByUserId(userId);
        } 

這樣的寫法有木有問題?

在我看來沒有充分的理由不應該返回null,因為方法的使用者並不知道在何種條件下會得到null,從而導致臭名昭著的NullReferenceException異常。

如果由於其他原因導致無法得到一個User,我們應該拋出一個明確的異常供上層服務決定如何處理:

       public User GetUser(string userName, string password)
        {
            if ( /*for some reason*/)
               return new SpecificException("can't get this user because ....");
            
            return DB.GetByUserId(userId);
        } 

在我讀過的開源項目中我幾乎沒有見到過return null的寫法。能讓我一時想到的兩個linq方法FirstOrDefault()和LastOrDefault(),這兩個方法通過命名的方式提醒使用者該方法會返回null。

說到FirstOrDefault()方法讓我想起了很多人容易犯的另一個錯誤:

       public User GetUserById(Guid userId)
        {
            return list.FirstOrDefault(x=>x.UserId==userId);
        }

在確認數據庫中該userId必須對應一個User的情況下使用FirstOrDefault()方法,此種場景我會建議你果斷使用Single()方法。因為此時使用FirstOrDefault()會隱藏bug。你期望該userId必須得到一個User,如果Single()方法拋出異常則說明有bug出現,並且讓你在第一時間發現該bug。

F#為了減少null類型的使用引入了option類型,在將option用作函數的返回類型時,如果沒有對未定義的類型做處理,編譯器會報錯。

let invalidInt = None

match invalidInt with 
| Some x -> printfn "the valid value is %A" x
| None -> printfn "the value is None" 

如果此處的模式匹配忘記編寫None->分支,編譯器將會報錯,從而提醒你必須處理invalidInt值為None時的邏輯。但是在C#中使用null類型,編譯器給予不了我們幫助,所以我們應該避免return null這樣的代碼,你覺得呢?

剛才搜了一下stackoverflow,發現一篇很有意思的討論 Should a retrieval method return 'null' or throw an exception when it can't produce the return value? 我覺得里面的回答比較准確。


免責聲明!

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



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