从函数返回数据的最佳实践是什么?是返回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。

例子:

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”。还要使你的方法是静态的。

编辑:

通常这样的方法是一些“User”类的成员,不能访问它的实例成员。在这种情况下,方法应该是静态的,否则你必须创建一个“User”的实例,然后调用GetUserById方法,该方法将返回另一个“User”实例。我同意这很令人困惑。但是如果GetUserById方法是某个“DatabaseFactory”类的成员,那么将它作为实例成员是没有问题的。

请原谅我的伪php/代码。

我认为这真的取决于结果的预期用途。

如果你想编辑/修改返回值并保存它,那么返回一个空对象。这样,您就可以使用相同的函数在新对象或现有对象上填充数据。

假设我有一个函数,它接受一个主键和一个数据数组,用数据填充行,然后将结果记录保存到db。因为我打算用我的数据填充对象,所以从getter返回一个空对象可能是一个巨大的优势。这样,我可以在两种情况下执行相同的操作。无论如何都要使用getter函数的结果。

例子:

function saveTheRow($prim_key, $data) {
    $row = getRowByPrimKey($prim_key);

    // Populate the data here

    $row->save();
}

在这里,我们可以看到相同的一系列操作操作了该类型的所有记录。

但是,如果返回值的最终目的是读取数据并对数据做一些事情,那么我将返回null。这样,我可以非常快速地确定是否没有返回数据,并向用户显示适当的消息。

通常,我将在检索数据的函数中捕获异常(因此我可以记录错误消息等),然后从捕获中直接返回null。对于最终用户来说,问题是什么通常并不重要,因此我发现最好将错误记录/处理直接封装在获取数据的函数中。如果你在任何大公司维护一个共享的代码库,这是特别有益的,因为你可以强制适当的错误记录/处理,即使是最懒的程序员。

例子:

function displayData($row_id) {
    // Logging of the error would happen in this function
    $row = getRow($row_id);
    if($row === null) {
        // Handle the error here
    }

    // Do stuff here with data
}

function getRow($row_id) {
 $row = null;
 try{
     if(!$db->connected()) {
   throw excpetion("Couldn't Connect");
  }

  $result = $db->query($some_query_using_row_id);

  if(count($result) == 0 ) {
   throw new exception("Couldn't find a record!");
  }

  $row = $db->nextRow();

 } catch (db_exception) {
  //Log db conn error, alert admin, etc...
  return null; // This way I know that null means an error occurred
 }
 return $row;
}

这是我的一般原则。到目前为止,它运行得很好。

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

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

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

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

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

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

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