你写的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

相关文章
相关标签/搜索