从函数返回数据的最佳实践是什么?是返回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,如果我正在寻找一组对象,但没有对象,则返回空集合。

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

其他回答

我会说返回null而不是空对象。

但你在这里提到的具体例子, 您正在通过用户id搜索用户,即排序 那个用户的键,在这种情况下,我可能想要 如果没有用户实例,则抛出异常 发现。

这是我通常遵循的规则:

如果通过主键查找操作没有找到结果, 把ObjectNotFoundException。 如按任何其他标准没有发现结果, 返回null。 如果通过非关键条件查找未找到结果,则可能返回多个对象 返回一个空集合。

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

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

如果用户没有被找到的情况经常出现,你想要根据情况以各种方式处理(有时抛出异常,有时替换一个空用户),你也可以使用接近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();
}

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

我不喜欢从任何方法返回null,而是使用Option函数类型。不返回结果的方法返回空选项,而不是null。

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

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

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

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

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