Tuesday, May 15, 2012

Simplify Null-Reference Handling of Properties in C#

A few months ago I wrote about a simple design rule that helped us to get almost rid of this annoying "Object reference not set to an instance of an object" exception, here.

In this post I want to show another way to simplify the handling of null-references. In particular, collection properties that can be null.

Let's start with a small piece of code:
class Customer {
   public string Name { get; set; }
   public ICollection<Contact> Contacts { get; set; }
}

// ...

Customer customer = GetCustomer(1);
foreach (var contact in customer.Contacts)
   Console.WriteLine(contact.FirstName);

Looks fine and there seem to be nothing special to talk about. Due to the rule I showed in the other post, GetCustomer will never return null. Unfortunately, the Contacts property is still not guaranteed not to be null. If Contacts is null we are again in front of our old "friend" NullReferenceException.

The straight forward approach is to always add an if-condition to ensure that our property is set to any value before we can iterate through.
Customer customer = GetCustomer();
if (customer.Contacts != null) {
   foreach (var contact in customer.Contacts)
      Console.WriteLine(contact.FirstName);
}
My problem with this is that developers (like me) tend to be lazy. We don't want to always add the condition and the additional scope.

Wouldn't it be nice to be able to write something like this?
Customer customer = GetCustomer();
foreach (var contact in customer.Contacts.NotNull()) // <= notice the NotNull()
   Console.WriteLine(contact.FirstName);
Luckily .NET 4.0 makes this possible with a simple extension method. Extension methods are not only static at design-time, but also behave as any other static methods at run-time. Any call of an extension method on a null reference will be routed into the extension method without any reference validation.

Due to this behavior of .NET, we are able to create this very simple extension method.
public static IEnumerable<T> NotNull<T>(this IEnumerable<T> collection) {
   return collection ?? new T[0];
}

Yes, this only helps when iterating through the list. But, from my experience, this covers about 90% of use cases.

Attention, keep in mind to always return an empty, immutable collection - like an array. If you would return an instance of a List<T> you might run into unexpected behaviors. The list would not become assigned to the parent component and any changes would not take any effect to the parent.

2 comments:

  1. Personally, my collection properties usually end up like this

    ICollection _items;

    public ICollection Items {
    get {
    return (_items ?? (_items = new List()));
    }
    }

    though i do like the extension method for other reasons.

    ReplyDelete
    Replies
    1. Thanks for your feedback.

      Yes, I also like the lazy initialization approach. The NotNull is especially handy when working with .NET classes or 3rd party components.

      Cheers
      Flo

      Delete