C# 函数应该返回 null 还是空对象?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1626597/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Should functions return null or an empty object?
提问by 7wp
What is the best practicewhen returning data from functions. Is it better to return a Null or an empty object? And why should one do one over the other?
从函数返回数据时的最佳实践是什么。返回 Null 或空对象更好吗?为什么要一个人做一个?
Consider this:
考虑一下:
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;
}
Lets pretend that there would be valid cases in this program that there would be no user information in the database with that GUID. I Would imagine that it would not be appropriate to throw an exception in this case?? Also I am under the impression that exception handling can hurt performance.
让我们假设在这个程序中存在有效的情况,即数据库中没有具有该 GUID 的用户信息。我会想象在这种情况下抛出异常是不合适的??另外我的印象是异常处理会损害性能。
采纳答案by ljs
Returning null is usually the best idea if you intend to indicate that no data is available.
如果您打算表明没有可用数据,则返回 null 通常是最好的主意。
An empty object implies data has been returned, whereas returning null clearly indicates that nothing has been returned.
空对象表示已返回数据,而返回 null 明确表示未返回任何内容。
Additionally, returning a null will result in a null exception if you attempt to access members in the object, which can be useful for highlighting buggy code - attempting to access a member of nothing makes no sense. Accessing members of an empty object will not fail meaning bugs can go undiscovered.
此外,如果您尝试访问对象中的成员,返回 null 将导致 null 异常,这对于突出显示错误代码很有用 - 尝试访问没有任何内容的成员是没有意义的。访问空对象的成员不会失败,这意味着错误可能未被发现。
回答by Rex M
It depends on what makes the most sense for your case.
这取决于什么对您的案例最有意义。
Does it make sense to return null, e.g. "no such user exists"?
返回空值是否有意义,例如“不存在这样的用户”?
Or does it make sense to create a default user? This makes the most sense when you can safely assume that if a user DOESN'T exist, the calling code intends for one to exist when they ask for it.
还是创建默认用户有意义?当您可以安全地假设如果一个用户不存在,调用代码打算在他们请求时存在一个用户时,这是最有意义的。
Or does it make sense to throw an exception (a la "FileNotFound") if the calling code is demanding a user with an invalid ID?
或者,如果调用代码要求用户使用无效 ID,那么抛出异常(“FileNotFound”)是否有意义?
However - from a separation of concerns/SRP standpoint, the first two are more correct. And technicallythe first is the most correct (but only by a hair) - GetUserById should only be responsible for one thing - getting the user. Handling its own "user does not exist" case by returning something else could be a violation of SRP. Separating into a different check - bool DoesUserExist(id)
would be appropriate if you do choose to throw an exception.
但是 - 从关注点分离/SRP 的角度来看,前两个更正确。从技术上讲,第一个是最正确的(但仅差一点) - GetUserById 应该只负责一件事 - 获取用户。通过返回其他内容来处理自己的“用户不存在”的情况可能违反 SRP。分离到不同的检查 -bool DoesUserExist(id)
如果您确实选择抛出异常,这将是合适的。
Based on extensive comments below: if this is an API-level design question, this method could be analogous to "OpenFile" or "ReadEntireFile". We are "opening" a user from some repository and hydrating the object from the resultant data. An exception could beappropriate in this case. It might not be, but it could be.
基于以下广泛评论:如果这是一个 API 级设计问题,则此方法可能类似于“OpenFile”或“ReadEntireFile”。我们正在从某个存储库“打开”一个用户,并从结果数据中提取对象。在这种情况下,例外可能是合适的。它可能不是,但它可能是。
All approaches are acceptable - it just depends, based on the larger context of the API/application.
所有方法都是可以接受的——这取决于 API/应用程序的更大上下文。
回答by Alex Moore
I personally would return null, because that is how I would expect the DAL/Repository layer to act.
我个人会返回 null,因为这是我希望 DAL/Repository 层起作用的方式。
If it doesn't exist, don't return anything that could be construed as successfully fetching an object, null
works beautifully here.
如果它不存在,不要返回任何可以被解释为成功获取对象的东西,null
在这里工作得很好。
The most important thing is to be consistant across your DAL/Repos Layer, that way you don't get confused on how to use it.
最重要的是在你的 DAL/Repos 层上保持一致,这样你就不会对如何使用它感到困惑。
回答by Charles Bretana
This is a business question, dependent on whether the existence of a user with a specific Guid Id is an expected normal use case for this function, or is it an anomaly that will prevent the application from successfully completing whatever function this method is providing the user object to...
这是一个业务问题,取决于具有特定 Guid Id 的用户的存在是否是此功能的预期正常用例,还是会阻止应用程序成功完成此方法为用户提供的任何功能的异常反对...
If it's an "exception", in that the absence of a user with that Id will prevent the application from successfully completing whatever function it is doing, (Say we're creating an invoice for a customer we've shipped product to...), then this situation should throw an ArgumentException (or some other custom exception).
如果它是一个“例外”,因为缺少具有该 ID 的用户将阻止应用程序成功完成它正在执行的任何功能,(假设我们正在为我们将产品运送到的客户创建发票...... ),那么这种情况应该抛出一个 ArgumentException(或其他一些自定义异常)。
If a missing user is ok, (one of the potential normal outcomes of calling this function) then return a null....
如果丢失的用户没问题(调用此函数的潜在正常结果之一),则返回 null....
EDIT: (to address comment from Adam in another answer)
编辑:(在另一个答案中解决亚当的评论)
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,boolean,无论如何 - 这是一个实现细节)。
But if all processes within the application requirea user, I would still throw the exception in this method...
但是如果应用程序中的所有进程都需要一个用户,我仍然会在这个方法中抛出异常......
回答by Jacob Mattison
It will vary based on context, but I will generally return null if I'm looking for one particular object (as in your example) and return an empty collection if I'm looking for a set of objects but there are none.
它会因上下文而异,但如果我正在寻找一个特定的对象(如您的示例),我通常会返回 null,如果我正在寻找一组对象但没有对象,则返回一个空集合。
If you've made a mistake in your code and returning null leads to null pointer exceptions, then the sooner you catch that the better. If you return an empty object, initial use of it may work, but you may get errors later.
如果您在代码中犯了错误并且返回 null 会导致空指针异常,那么您越早发现它越好。如果您返回一个空对象,最初使用它可能会起作用,但稍后可能会出错。
回答by Fernando
Personally, I use NULL. It makes clear that there is no data to return. But there are cases when a Null Objectmay be usefull.
就个人而言,我使用 NULL。它清楚地表明没有数据要返回。但在某些情况下,空对象可能有用。
回答by whatsisname
I typically return null. It provides a quick and easy mechanism to detect if something screwed up without throwing exceptions and using tons of try/catch all over the place.
我通常返回 null。它提供了一种快速简便的机制来检测是否有问题,而不会抛出异常并在整个地方使用大量的 try/catch。
回答by Darin Dimitrov
If your return type is an array then return an empty array otherwise return null.
如果您的返回类型是数组,则返回一个空数组,否则返回 null。
回答by Kamarey
The best in this case return "null" in a case there no a such user. Also make your method static.
在这种情况下最好在没有此类用户的情况下返回“null”。还要使您的方法静态。
Edit:
编辑:
Usually methods like this are members of some "User" class and don't have an access to its instance members. In this case the method should be static, otherwise you must create an instance of "User" and then call GetUserById method which will return another "User" instance. Agree this is confusing. But if GetUserById method is member of some "DatabaseFactory" class - no problem to leave it as an instance member.
通常,像这样的方法是某些“用户”类的成员,并且无法访问其实例成员。在这种情况下,该方法应该是静态的,否则您必须创建一个“User”实例,然后调用 GetUserById 方法,该方法将返回另一个“User”实例。同意这是令人困惑的。但是,如果 GetUserById 方法是某个“DatabaseFactory”类的成员 - 将其保留为实例成员没有问题。
回答by Henk Holterman
You should throw an exception (only) if a specific contract is broken.
In your specific example, asking for a UserEntity based on a known Id, it would depend on the fact if missing (deleted) users are an expected case. If so, then return null
but if it is not an expected case then throw an exception.
Note that if the function was called UserEntity GetUserByName(string name)
it would probably not throw but return null. In both cases returning an empty UserEntity would be unhelpful.
如果特定合同被破坏,您应该(仅)抛出异常。
在您的具体示例中,根据已知 Id 请求 UserEntity,这取决于丢失(删除)用户是否是预期情况。如果是,则返回,null
但如果不是预期的情况,则抛出异常。
请注意,如果调用该函数,UserEntity GetUserByName(string name)
它可能不会抛出而是返回 null。在这两种情况下,返回空的 UserEntity 都无济于事。
For strings, arrays and collections the situation is usually different. I remember some guideline form MS that methods should accept null
as an 'empty' list but return collections of zero-length rather than null
. The same for strings. Note that you can declare empty arrays: int[] arr = new int[0];
对于字符串、数组和集合,情况通常是不同的。我记得一些指导表单 MS 方法应该接受null
作为“空”列表但返回零长度的集合而不是null
. 字符串也是一样。请注意,您可以声明空数组:int[] arr = new int[0];