collection

Fix Downstream Collection Problems

 

Recently I’ve talked about how we should always initialise collection types with an empty collection. Not doing so will cause unnecessary NullReferenceExceptions. This guidance extends to return values – Never return a null for a collection type. 

What if we called a method that returned a null collection? The called class comes from a 3rd party library, and we can’t fix the problem at the source. Or the called method is lengthy legacy code lacking unit tests for us to make modifications without introducing new bugs. 

If in turn, we are passing through this return collection type to our clients, we may propagate the problematic null collection further. It is our responsibility to ensure clients of our method get sane and expected values even when we receive nonsense. So, how do we ensure our callers don’t get a dorky null collection?

Let’s look at an example:

  public IEnumerable<Customer> SearchCustomers(string firstName, string lastName, string address)
  {
     // builds up criteria from parameters

     return Searcher.FindMatchingCustomers(criteria);
  }

It seems the purpose of the example method is to construct the search criteria from the parameters and then find matching customers. Unfortunately, Searcher.FindMatchingCustomers() sometimes returns a null collection when there are no matching customers. FindMatchingCustomers() is convoluted legacy code without unit tests which we do not want to modify, if at all possible. 

So, how do we ensure our clients always get a collection even when we do not? We perform a null check:

  public IEnumerable<Customer> SearchCustomers(string firstName, string lastName, string address)
  {
     // builds up criteria from parameters

     var customers = Searcher.FindMatchingCustomers(criteria);
     if (customers == null)
        return new List<Customer>();
     return customers;
  }

In .NET, a compact and elegant alternative is to use the null-coalescing operator, ??:

  public IEnumerable<Customer> SearchCustomers(string firstName, string lastName, string address)
  {
     // builds up criteria from parameters

     var customers = Searcher.FindMatchingCustomers(criteria);
     return customers ?? new List<Customer>();
  }

or even better:

  public IEnumerable<Customer> SearchCustomers(string firstName, string lastName, string address)
  {
     // builds up criteria from parameters

     var customers = Searcher.FindMatchingCustomers(criteria);
     return customers ?? Enumerable.Empty<Customer>();
  }

The point isn’t about the specific implementation of converting a received null into an empty collection before we pass it on. 

Instead, it’s that as responsible developers, we fix problems and don’t leave our callers hanging.

Ideally, I recommend repairing any collection initialisation problems at the source. However, this is an acceptable way of stopping the propagation of a possible null collection quickly and safely.

0 replies

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply