从函数返回数据的最佳实践是什么?是返回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的用户信息。我认为在这种情况下抛出异常是不合适的??另外,我的印象是异常处理会损害性能。


当前回答

如果用户没有被找到的情况经常出现,你想要根据情况以各种方式处理(有时抛出异常,有时替换一个空用户),你也可以使用接近f#的Option或Haskell的Maybe类型,它显式地将“无值”情况与“发现了一些东西!”数据库访问代码看起来像这样:

public Option<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 Option<UserEntity>.Nothing; 
 else
    return Option.Just(existingUserEntity);
}

并且像这样使用:

Option<UserEntity> result = GetUserById(...);
if (result.IsNothing()) {
    // deal with it
} else {
    UserEntity value = result.GetValue();
}

不幸的是,每个人似乎都有自己喜欢的类型。

其他回答

我对答案的数量感到困惑(在整个网络上),说你需要两个方法:“IsItThere()”方法和“GetItForMe()”方法,所以这导致了一个竞争条件。一个函数返回null,将它分配给一个变量,并在一次测试中检查变量是否为null,这有什么问题?我以前的C代码中充斥着

if (NULL !=(变量=函数(参数…))){

因此,您可以同时获得变量中的值(或null)和结果。这个成语已经被遗忘了吗?为什么?

为了代码库的健康,我认为函数不应该返回null。我能想到几个原因:

将有大量的保护子句处理空引用if (f() != null)。

什么是空,它是一个公认的答案还是一个问题?null是特定对象的有效状态吗?(假设您是代码的客户端)。我的意思是所有引用类型都可以为空,但是它们应该为空吗?

当你的代码库不断增长时,使用null几乎总是会不时地产生一些意想不到的NullRef异常。

有一些解决方案,测试者-执行者模式或从函数式编程实现选项类型。

在我们的业务对象中,我们有两个主要的Get方法:

为了让事情在语境中变得简单,或者你的问题是:

// Returns null if user does not exist
public UserEntity GetUserById(Guid userId)
{
}

// Returns a New User if user does not exist
public UserEntity GetNewOrExistingUserById(Guid userId)
{
}

第一种方法用于获取特定的实体,第二种方法用于在网页上添加或编辑实体。

这使我们能够在使用它们的上下文中两全其美。

我个人会返回null,因为这是我所期望的DAL/Repository层的操作方式。

如果它不存在,不要返回任何可以被解释为成功获取对象的东西,null在这里工作得很好。

最重要的是在你的DAL/Repos层保持一致,这样你就不会对如何使用它感到困惑。

这取决于什么对你的案子最有意义。

返回null是否有意义?“不存在这样的用户”?

或者创建一个默认用户有意义吗?当您可以安全地假设如果用户不存在,则调用代码在请求时希望用户存在时,这是最有意义的。

或者,如果调用代码要求使用无效ID的用户,抛出异常(如“FileNotFound”)是否有意义?

然而,从分离关注点/SRP的角度来看,前两点更为正确。从技术上讲,第一个是最正确的(但只差一点点)——GetUserById应该只负责一件事——获取用户。通过返回其他内容来处理自己的“用户不存在”情况可能违反SRP。如果您确实选择抛出异常,则分隔为不同的check - bool DoesUserExist(id)是合适的。

根据下面大量的评论:如果这是一个api级别的设计问题,这个方法可以类似于“OpenFile”或“readwholfile”。我们正在从某个存储库中“打开”一个用户,并从结果数据中补充对象。在这种情况下,一个例外可能是合适的。也许不是,但也有可能。

所有的方法都是可以接受的——这取决于API/应用程序的上下文。