你寫的return null正確嗎?

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

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

這樣的寫法有木有問題?數據庫

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

若是因爲其餘緣由致使沒法獲得一個User,咱們應該拋出一個明確的異常供上層服務決定如何處理:ui

       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。this

說到FirstOrDefault()方法讓我想起了不少人容易犯的另外一個錯誤:code

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

在確認數據庫中該userId必須對應一個User的狀況下使用FirstOrDefault()方法,此種場景我會建議你果斷使用Single()方法。由於此時使用FirstOrDefault()會隱藏bug。你指望該userId必須獲得一個User,若是Single()方法拋出異常則說明有bug出現,而且讓你在第一時間發現該bug。htm

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

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這樣的代碼,你以爲呢?ip

剛纔搜了一下stackoverflow,發現一篇頗有意思的討論 Should a retrieval method return 'null' or throw an exception when it can't produce the return value? 我以爲裏面的回答比較準確。ci

相關文章
相關標籤/搜索