从函数返回数据的最佳实践是什么?是返回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,而是使用Option函数类型。不返回结果的方法返回空选项,而不是null。

而且,不能返回结果的方法应该通过名称来指明。我通常把Try或TryGet或TryFind放在方法名称的开头,以表明它可能返回一个空结果(例如TryFindCustomer, TryLoadFile等)。

这让调用者可以对结果应用不同的技术,比如收集管道(参见Martin Fowler的收集管道)。

下面是另一个使用返回Option而不是null来降低代码复杂性的示例:如何降低圈复杂度:选项函数类型

其他回答

它将根据上下文而变化,但如果我正在寻找一个特定的对象(如您的示例),我通常会返回null,如果我正在寻找一组对象,但没有对象,则返回空集合。

如果你在代码中犯了一个错误,返回null会导致空指针异常,那么越早发现越好。如果您返回一个空对象,最初使用它可能会工作,但稍后可能会得到错误。

如果返回的对象是可以迭代的对象,我将返回一个空对象,这样我就不必首先测试null。

例子:

bool IsAdministrator(User user)
{
    var groupsOfUser = GetGroupsOfUser(user);

    // This foreach would cause a run time exception if groupsOfUser is null.
    foreach (var groupOfUser in groupsOfUser) 
    {
        if (groupOfUser.Name == "Administrators")
        {
            return true;
        }
    }

    return false;
}

如果您打算表示没有可用的数据,返回null通常是最好的主意。

空对象表示已返回数据,而返回null则明确表示没有返回任何数据。

此外,如果试图访问对象中的成员,返回null将导致null异常,这对于突出显示有bug的代码很有用——试图访问没有任何成员的成员是没有意义的。访问空对象的成员不会失败,这意味着bug不会被发现。

我更喜欢null,因为它与空合并操作符(??)兼容。

(仅)在特定契约被破坏时抛出异常。 在您的特定示例中,请求基于已知Id的UserEntity,这将取决于丢失(删除)用户是否是预期情况。如果是,则返回null,但如果不是预期的情况,则抛出异常。 注意,如果函数名为UserEntity GetUserByName(字符串名),它可能不会抛出而是返回null。在这两种情况下,返回空的UserEntity都没有帮助。

对于字符串、数组和集合,情况通常是不同的。我记得MS的一些指导原则,方法应该接受null作为一个“空”列表,但返回零长度的集合而不是null。字符串也是一样。注意,你可以声明空数组:int[] arr = new int[0];