Attention: We are retiring the ASP.NET Community Blogs. Learn more >

Avoid returning "null" and use the Null Object pattern?

When I build applications and add methods to return a list of objects, I make it robust. So I always return an instance of the list instead or returning null. The reason is because I like the use of Count and also use foreach. I don't want to add extra code to see if the method returns null. For example:

public IList<string> GetCultures()
{
    IList<string> cultures = new List<string>();

    //...

    return cultures;
}

 

Then when I make a call to the GetCultures method I can see if it contains any cultures by using Count, and if I need to list Cultures I can also use foreach without getting a null exception.

IList<string> cultures = GetCultures();

if (cultures.Count > 0 )
   //..


foreach (var culture in GetCultures())
   //..


If I prefer Robustness before Correctness I return null if I only need to return a single object, for example:

public static Culture GetCulture(string cultureCode)
{
    Culture culture = null;
            
    //..

    return culture;
}

 

In this case I need to see if the returned object is null or not before using it.

Culture culture = GetCulture();

if (cultures !=null)


I could also throw an exception if the cultureCode could not be located, in that way I will never return null. But I try to avoid throwing exception and use try catch block when I try to get an object. The reason is performance and also skip adding several try catch block in my code.

public static Culture GetCulture(string cultureCode)
{
    Culture culture = null;
            
    //Can't locate the culture throw an exception

    return culture;
}

 

Culture culture = null;

try
{
    culture = GetCulture();
}
catch
{
    //...
}


I only throw an exception when it's really an exception, for example the cultureCode was in a correct format or wasn't specified etc. Everything is based on the type of application, and if Robustness is more important than Correctness. Another solution is to use the Null Object Pattern and always return an instance of an object.

Culture culture = GetCulture();

if (cultures.IsNull)


Or use the Cultures other members and not get a null exception. The Null Object Pattern is also useful if I always want to return a default value. For example if I want to get a Customer and the Customer can't be located, I could return a John Doe ;) I don't use the Null Object Pattern so often in my applications.

What solution do you use or prefer when returning a list or single object and why?

13 Comments

  • As I am reading you post, I start thinking about creating an extension method on object that would let me do object.IsNull(), it would simply be an overload of object == null, but would read better. Sort of like Nullable types HasValue.

    How would the Null Object look like? Something like NullObject?

  • Egil: I was thinking about the same thing as you. I guess I will write an extension method for object that has an IsNull method.

    Fredrik: I totally agree with you and I do the same thing as in your examples. I prefer to return an empty collection instead of null.

    OrderCollection orders = Order.GetOrders();
    foreach (Order in orders) //returns an exception if null, is ignored if empty
    Order.Delete();

    I prefer to not have any orders deleted than get an exception. :-)

  • I Think throw exception is Better than another one.
    because every one can read my code and understand it.
    in Layered Architecture We Can Read Exceptions And Fix Them.

  • Hello.

    Well, most of the times, I'm using your approach and I'm returning null for non existing single objects and an empty list for a non existing collection of objects. Null objects are great, but I'm not sure if they're useful on the UI (which is where most of my objects end up)...

  • Hello,

    I'm using the following technique in collections (code snippet can help):

    if(coll != null && coll.Count > 0) {...}

    Is there a overhead in instance a empty List?

  • I think both approaches have good and bad features. The nice thing about using the Null Object pattern is that it makes null a first-class citizen in the language.

  • I don't think that it is a good behavior to ask an object if it's null or not... it's just misleading. In fact, that means that the object itself (which is not existent if it's null) knows about his null-state.

  • While I can see the advantage of the Null Object Pattern, I am not quite a fan of it. I don't always do like this (I tend to dislike you-must-always philosophies, since there will sometimes be cases where they simply do not fit in): if a method's return type is a list of some kind, it should return such an instance that may or may not be empty. If a method's return type is a single object, it should throw an exception if the returned object would be vital for the continued execution of the program. If the return type is a single object, that is not vital for continued execution, a null reference could do fine.

    Now, how do I decide whether a certain object is vital for the caller or not? That's not always obvious and when in doubt, I think I prefer to throw an exception. The main reasons are that exceptions are obvious; they force the developer of the calling code to make an active decision. It makes erroneous calls clear earlier in the development cycle, so that you can write the proper checks to avoid them at a higher level in the code. Also, a null reference can travel some distance from the call that returned it until it actually causes some trouble, and so it may be trickier to troubleshoot. But I would say that an object instance, having IsNull = true might travel even further, being even trickier to troubleshoot.

  • It is obvious that you should return an empty list when the function worked as intended and that there is not any objects to be fetched, but if something goes wrong in that function, it is probably better to give the user of the code a hint. The bool TryX(out val) pattern were you have a logger in place is probably the optimal solution.

    IsNull() or == null is probably not the same when it comes to performance. == null is a more common pattern than IsNull() too (espcially as extension methods is a rather new addition to C#).

  • When returning a single object I return null if not found. Using "Null Object Pattern", in this case, just adds a "Special Case" to check for instead of null.

    To "return" a collection I prefer to pass it as a parameter, instead of returning it, and fill the list in the method. That will be easier to understand for the developer, especially if you name the method ok :). He/she creates the list him/herself and knows it is not null (you cannot even pass a null reference as "ref") and can use Count afterwards.

    IList cultures = new List();

    FillCurrentCultures(ref IList cultures);

    if(cultures.Count>0){
    // ...
    }

  • I prefer , returning empty list rather null, i guess .net framework design guidlines like empty list as well :-)

  • I totally agree with your null stance for collections. It frustrates me to no end when my colleagues return null instead of an empty list.

  • I just started using a "ResultFact" return from non-trivial methods that has an IsGood, Message, and optionally a generic Content property. That way I can return a common object from all these methods and communicate both the result and any details back to the caller without lapsing into using Exceptions for non-exceptional cases. I'm not sure if this will prove out over the long term, but it almost feels like it should be part of the framework (sort of like tuple but in context)

    public class ResultFact
    {
    public bool IsGood { get; set; }
    public string Message { get; set; }

    public ResultFact()
    {

    }

    public ResultFact(bool isGood, string message)
    {
    IsGood = isGood;
    Message = message;
    }

    public ResultFact WithError(string error)
    {
    IsGood = false;
    Message = error;
    return this;
    }
    }

    public sealed class ResultFact : ResultFact
    {
    public T1 Content { get; private set; }

    public ResultFact():
    base()
    {

    }

    public ResultFact(bool isGood, string message) :
    base(isGood, message)
    {
    }

    public new ResultFact WithError( string error )
    {
    IsGood = false;
    Message = error;
    return this;
    }

    public ResultFact WithContent( T1 content )
    {
    IsGood = true;
    Content = content;
    return this;
    }

    public ResultFact WithContent( T1 content, string message )
    {
    IsGood = true;
    Content = content;
    Message = message;
    return this;
    }
    }

Comments have been disabled for this content.