6

I have a public method which searches for an image and if the image exists, it returns it as a byte array.

What the method should return, if the image doesn't exist? (the image not existing is not an exception, but expected possibility)

Should I return an empty byte[] array, or should it return byte?[] set to null instead?

Which one is more in tune with conventions?

2
  • 2
    If you wanted to return null, why wouldn't you just return a byte[] reference which is null? No need to use byte[]. Commented Aug 14, 2014 at 7:26
  • 2
    byte[] is reference type. You can do return null directly: byte[] Method() { return null; }. byte?[] means that you will create array of nullable bytes (so any / all of byte could be null, ) - that make no sense in this case. Commented Aug 14, 2014 at 7:27

5 Answers 5

12

I would return null (just as a byte[] - all arrays are reference types). Returning an empty array will lead the caller to think they can try to load that data as an image - which they can't. Returning a null reference makes it very easy to differentiate between "present and empty" vs "not present at all".

In other cases where the image being missing is an indication of a significant system problem, I'd consider an exception though. It sounds like that's not the case here.

Note that this is significantly different to a normal method returning a collection of individual elements - you don't care about each byte as a separate entity in the way that you would for a method returning List<Person> for example; here the byte[] is effectively a blob. I would regard it as a single chunk of data which happens to be represented as an array rather than a collection. To put it another way: think about it as if your method were declared to return a Blob type instead of an array... would you return a null reference, or an instance of Blob with no data?

Sign up to request clarification or add additional context in comments.

6 Comments

I also tend to consider the naming of the methods in this case, going by the Parse/TryParse pattern. If I call a method that says "do this", I would rather it threw an exception than say "I couldn't do it" using a return value. On the other hand, if I call a method that says "try to do this", then a bool/no result signature is better. So if the method here is "LoadImage", I would personally want it to throw an exception. If the image is just as (or even more) likely to not be there, returning null/false is the best way (again, my opinion), from TryLoadImage.
I thought an exception was to be used in cases of behavior that was not expected. This image not existing is very expected behavior. And on top of that, isn't catching an exception infinitely slower than doing if (img == null)?
@LasseV.Karlsen: Yes, I agree that naming is important - although depending on the prevalence of this sort of call in the system, it may be that the ones that do throw the exception are rarer, and should be named LoadImageOrFail for example.
@Fred: You shouldn't be doing it if you'd be catching the exception - but as I said in my answer, in other cases where this would be an indication of a system problem, and exception would be suitable. In your case, returning null is more appropriate.
@Fred: Yes, that's the whole point - if the exception is thrown because the system is in a bad state, then the program should crash (or the particular request should fail, for a server). You'd often have a very general catch block at a reasonably high level, but you should avoid throwing an exception just for it to be caught by the immediate caller - in most cases, anyway.
|
3

Neither alternative is good for situations when something does not exist: returning an empty array of bytes is wrong, because the users cannot distinguish between finding an image that is actually empty, and not finding an image. Returning null is slightly better, but the users may forget to null-check the return.

Two alternatives that work better are returning a not found result as a bool while setting the result in an out parameter, and throwing an exception. Both approaches make the "image not found" condition explicit to the users of your API, making it harder to miss.

bool TryLookUpImage(string name, out byte[] image) {
    ...
}
...
byte[] image;
if (TryLookUpImage(imageName, out image)) {
    // Display image
} else {
    // Display error
}

1 Comment

+1 Method name probably should be aligned with other TryXXXX methods... Maybe TryFind ?
3

It is considered a best practice to NEVER return null when returning a collection or enumerable. "ALWAYS" return an empty enumerable/collection. It prevents the aforementioned nonsense, and prevents your car getting egged by co-workers and users of your classes.

In general that's correct, but there are cases when returning null isn't wrong. so the "ALWAYS" has to be omitted.

Also, a great source is the Framework Design Guidelines 2nd Edition (pg. 256):

DO NOT return null values from collection properties or from methods returning collections. Return an empty collection or an empty array instead.

2 Comments

I agree in general, but this is a different matter. This isn't a collection to be iterated over - it's basically a blob.
I would not generalize this. Imho it is best practice to return null if a searched resource does not exist. If you'd return an empty collection that would mean: here is your image, it is empty.
2
  1. Return a null since as @JonSkeet points out, since the result is not used as a collection but as a single blob. Maybe name the method GetImageOrNull so the user clearly knows he should expect to be given a null.

  2. You can also do it like the Dictionary.TryGetValue method (link) and return a boolean that says if it's valid. This could look like this (note that the method is named similar and - if used consistently - makes it obvious how to use it):

    public bool TryGetImage(SomeParameter param, out byte[] image)
    {
        bool imageFound;
        //...
        return imageFound;
    }
    
  3. Change the return type to a IEnumerable<byte[]> instead. This could be interpreted as an array of images. Then you can return an empty byte[][]. Makes only sense if it's ever possible to return more than one image. This would also follow Atanas advice, which I second for collections.

2 Comments

Third option should probably be IEnumerable<byte[]> if you try to align with any other API... Arrays are just pain and don't allow lazy evaluation...
@AlexeiLevenkov: Although I don't always prefer lazy evaluation, it's a good thing to enable it ;-). Maybe it would even be better to return the image as an own type like ImageData and not an byte[]. Would make things even more readable... But I think that's out of scope for the current question.
0

I would name the method

bool TryLoadImage(name, out byte[] image)

Then it is clear to anyone reading the code that the method expects not to be able to load some images. And therefore image can not be assumed to contain a valid image after the call.

Setting the image to null, rather than a empty array is best for all the reasons Jon Skeet gave.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.