Let’s say you are given the following…
List<Thing> theThings = fubar.Things.All();
If there were nothing to return, what would you expect fubar.Things.All() to return?
Edit:
Thanks for the opinions. I’ll wait a bit and accept the entry with the most ups.
I agree with the responses so far, particularly those suggesting an empty collection. A vendor provided an API with several calls similar to the example above. A vendor who did $4.6 million in revenue via their API(s) last year, BTW. They do something I fundamentally disagree with — they throw an exception.
6
Of the two possibilities (i.e. returning a null
or returning an empty collection) I would pick returning an empty collection, because it lets the caller to skip a check of the returned value. Instead of writing this
List<Thing> theThings = fubar.Things.All();
if (theThings != null) {
for (Thing t : theThings) {
t.doSomething();
}
}
they would be able to write this:
List<Thing> theThings = fubar.Things.All();
for (Thing t : theThings) {
t.doSomething();
}
This second code fragment is shorter and easier to read, because the nesting level is lower by one.
3
I would expect an empty list. theThings
would still be an object, but theThings.Count
or theThings.size()
would return 0
.
Design issues like that are addressed by Null Object pattern
…Instead of using a null reference to convey absence of an object (for instance, a non-existent customer), one uses an object which implements the expected interface, but whose method body is empty. The advantage of this approach over a working default implementation is that a Null Object is very predictable and has no side effects: it does nothing.
For example, a function may retrieve a list of files in a directory and perform some action on each. In the case of an empty directory, one response may be to throw an exception or return a null reference rather than a list. Thus, the code which expects a list must verify that it in fact has one before continuing, which can complicate the design…
Suggestion particularly applicable in your case (returning List
when there are no Thing
s) is:
…By returning a null object (i.e. an empty list) instead, there is no need to verify that the return value is in fact a list. The calling function may simply iterate the list as normal, effectively doing nothing. It is, however, still possible to check whether the return value is a null object (e.g. an empty list) and react differently if desired.
You should, IMHO, return a EMPTY value.
I don’t know about C#, but in Java we have this:
List list = Collections.EMPTY_LIST;
Set set = Collections.EMPTY_SET;
Map map = Collections.EMPTY_MAP;
// For the type-safe
List<String> s = Collections.emptyList();
Set<Long> l = Collections.emptySet();
Map<Date> d = Collections.emptyMap();
http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Collections.html
2
I would return an empty collection over returning a null value because that way you can avoid writing a null verification in the calling code.
The two solutions they mean different things.
If there are just zero of the thing you are returning, you ALWAYS return an empty collection! Take the case of a directory listing. If there are no files in the directory you return an empty collection of files.
On the other hand, if the directory doesn’t exist, that’s not really appropriate. “I can’t return anything” means something compeltely different. In that case you should either return null or throw an exception depending on the situation, don’t just return an empty collection like nothing was wrong.
1