从函数返回数据的最佳实践是什么?是返回Null对象好还是返回空对象好?为什么要选择一种而不是另一种呢?

考虑一下:

public UserEntity GetUserById(Guid userId)
{
     //Imagine some code here to access database.....

     //Check if data was returned and return a null if none found
     if (!DataExists)
        return null; 
        //Should I be doing this here instead? 
        //return new UserEntity();  
     else
        return existingUserEntity;
}

让我们假设在这个程序中存在有效的情况,即数据库中没有具有该GUID的用户信息。我认为在这种情况下抛出异常是不合适的??另外,我的印象是异常处理会损害性能。


当前回答

我个人返回该对象的默认实例。原因是我希望该方法返回0到多或0到1(取决于该方法的目的)。使用这种方法,它将是任何类型的错误状态的唯一原因是,如果方法不返回任何对象,并且总是期望返回(就一对多或单数返回而言)。

至于假设这是一个业务领域的问题——我只是没有从等式的那一边看到它。返回类型的规范化是一个有效的应用程序体系结构问题。至少,它是编码实践标准化的主题。我怀疑是否有业务用户会说“在场景X中,只给他们一个null”。

其他回答

异步TryGet模式:

对于同步方法,我相信@Johann Gerell的回答是适用于所有情况的模式。

但是带有out参数的TryGet模式不适用于Async方法。

使用c# 7的元组文字,你现在可以这样做:

async Task<(bool success, SomeObject o)> TryGetSomeObjectByIdAsync(Int32 id)
{
    if (InternalIdExists(id))
    {
        o = await InternalGetSomeObjectAsync(id);

        return (true, o);
    }
    else
    {
        return (false, default(SomeObject));
    }
}

更多的肉要磨:让我们说我的DAL返回一个NULL的GetPersonByID,正如一些建议。我的(相当薄)BLL应该做什么,如果它收到一个NULL?传递NULL,并让最终消费者担心它(在这种情况下,一个ASP。网络页面)?让BLL抛出一个异常怎么样?

BLL可能正在被ASP使用。Net和Win App,或者其他类库——我认为期望最终消费者本质上“知道”GetPersonByID方法返回null是不公平的(除非使用空类型,我猜)。

My take (for what it's worth) is that my DAL returns NULL if nothing is found. FOR SOME OBJECTS, that's ok - it could be a 0:many list of things, so not having any things is fine (e.g. a list of favourite books). In this case, my BLL returns an empty list. For most single entity things (e.g. user, account, invoice) if I don't have one, then that's definitely a problem and a throw a costly exception. However, seeing as retrieving a user by a unique identifier that's been previously given by the application should always return a user, the exception is a "proper" exception, as in it's exceptional. The end consumer of the BLL (ASP.Net, f'rinstance) only ever expects things to be hunky-dory, so an Unhandled Exception Handler will be used instead of wrapping every single call to GetPersonByID in a try - catch block.

如果我的方法有明显的问题,请让我知道,因为我总是渴望学习。正如其他帖子所说,异常是代价高昂的事情,“先检查”的方法是好的,但异常应该只是例外。

我很喜欢这篇文章,很多关于“视情况而定”的好建议:-)

我们使用CSLA。NET,并且它认为失败的数据获取应该返回一个“空”对象。这实际上是相当烦人的,因为它要求检查obj。IsNew而不是obj == null。

正如前面提到的,null返回值将导致代码立即失败,从而降低了由空对象引起的隐形问题的可能性。

就我个人而言,我认为null更优雅。

这是一种非常常见的情况,我很惊讶这里的人似乎对此感到惊讶:在任何web应用程序中,数据通常是使用querystring参数获取的,这显然会被破坏,因此要求开发人员处理“未找到”的情况。

你可以这样处理:

if (User.Exists(id)) {
  this.User = User.Fetch(id);
} else {
  Response.Redirect("~/notfound.aspx");
}

...但是这每次都是对数据库的额外调用,这在高流量页面上可能是一个问题。而:

this.User = User.Fetch(id);

if (this.User == null) {
  Response.Redirect("~/notfound.aspx");
}

...只需要一个呼叫。

我通常返回null。它提供了一种快速而简单的机制来检测是否出现了错误,而不会抛出异常,也不会到处使用大量的try/catch。

我是一名法国IT专业的学生,所以请原谅我的英语不好。在我们的类中,我们被告知这样的方法永远不应该返回null,也不应该返回空对象。这种方法的用户应该在尝试获取对象之前首先检查他正在寻找的对象是否存在。

使用Java,我们被要求添加一个断言exists(object):“您不应该尝试访问一个不存在的对象”;在任何可能返回null的方法的开头,以表达“先决条件”(我不知道英文单词是什么)。

在我看来,这真的不容易使用,但这就是我正在使用的,等待更好的东西。