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


当前回答

把别人说的话用更简洁的方式来表达……

例外情况只适用于特殊情况

如果这个方法是纯数据访问层,我会说,给定一些参数,被包含在一个选择语句中,它将期望我可能找不到任何行,从中构建一个对象,因此返回null将是可接受的,因为这是数据访问逻辑。

另一方面,如果我希望我的参数反映一个主键,我应该只返回一行,如果我返回了不止一行,我就会抛出异常。0可以返回null, 2则不行。

现在,如果我有一些登录代码检查LDAP提供程序,然后检查DB以获得更多详细信息,并且我希望它们始终保持同步,那么我可能会抛出异常。正如其他人所说,这是商业规则。

Now I'll say that is a general rule. There are times where you may want to break that. However, my experience and experiments with C# (lots of that) and Java(a bit of that) has taught me that it is much more expensive performance wise to deal with exceptions than to handle predictable issues via conditional logic. I'm talking to the tune of 2 or 3 orders of magnitude more expensive in some cases. So, if it's possible your code could end up in a loop, then I would advise returning null and testing for it.

其他回答

这是一个业务问题,取决于具有特定Guid Id的用户的存在是否是该函数的预期正常用例,还是会阻止应用程序成功完成该方法向用户对象提供的任何功能的异常情况……

如果它是一个“异常”,因为缺少具有该Id的用户将阻止应用程序成功完成它正在做的任何功能,(假设我们正在为我们已向其发货的客户创建发票……),那么这种情况应该抛出ArgumentException(或其他一些自定义异常)。

如果没有用户(调用此函数的潜在正常结果之一),则返回空值....

编辑:(处理亚当在另一个回答中的评论)

If the application contains multiple business processes, one or more of which require a User in order to complete successfully, and one or more of which can complete successfully without a user, then the exception should be thrown further up the call stack, closer to where the business processes which require a User are calling this thread of execution. Methods between this method and that point (where the exception is being thrown) should just communicate that no user exists (null, boolean, whatever - this is an implementation detail).

但是如果应用程序中的所有进程都需要一个用户,我仍然会在这个方法中抛出异常……

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

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

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

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

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

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

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

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

把别人说的话用更简洁的方式来表达……

例外情况只适用于特殊情况

如果这个方法是纯数据访问层,我会说,给定一些参数,被包含在一个选择语句中,它将期望我可能找不到任何行,从中构建一个对象,因此返回null将是可接受的,因为这是数据访问逻辑。

另一方面,如果我希望我的参数反映一个主键,我应该只返回一行,如果我返回了不止一行,我就会抛出异常。0可以返回null, 2则不行。

现在,如果我有一些登录代码检查LDAP提供程序,然后检查DB以获得更多详细信息,并且我希望它们始终保持同步,那么我可能会抛出异常。正如其他人所说,这是商业规则。

Now I'll say that is a general rule. There are times where you may want to break that. However, my experience and experiments with C# (lots of that) and Java(a bit of that) has taught me that it is much more expensive performance wise to deal with exceptions than to handle predictable issues via conditional logic. I'm talking to the tune of 2 or 3 orders of magnitude more expensive in some cases. So, if it's possible your code could end up in a loop, then I would advise returning null and testing for it.

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

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

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