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


当前回答

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

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

其他回答

就我个人而言,我使用NULL。它清楚地表明没有数据要返回。但在某些情况下,空对象可能是有用的。

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

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

我倾向于

如果对象id不存在,在不知道它是否应该存在时返回null。 当对象id应该存在时,如果对象id不存在则抛出。

我用这三种类型的方法来区分这两种场景。 第一:

Boolean TryGetSomeObjectById(Int32 id, out SomeObject o)
{
    if (InternalIdExists(id))
    {
        o = InternalGetSomeObject(id);

        return true;
    }
    else
    {
        return false;
    }
}

第二:

SomeObject FindSomeObjectById(Int32 id)
{
    SomeObject o;

    return TryGetObjectById(id, out o) ? o : null;
}

第三:

SomeObject GetSomeObjectById(Int32 id)
{
    SomeObject o;

    if (!TryGetObjectById(id, out o))
    {
        throw new SomeAppropriateException();
    }

    return o;
}

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

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

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

在我们的业务对象中,我们有两个主要的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)
{
}

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

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