When is a reference to null not a null reference?

I was having a conversation with a programmer new to C# recently, who was rather confused by something similar to the following bit of code. He’d been looking at the source for a library on GitHub, and he didn’t understand why this could run without errors:

Widget widget = null;
// do stuff that may or may not assign an object to widget
widget.DoSomething();

To him, it seemed to be risking a NullReferenceException, as you can’t call a method on a null object.

Ordinarily this is true, but as I found myself explaining, there is one scenario where this code will run quite happily: When DoSomething() is an extension method.

Extension methods are not methods on the class you are referring to, they are static methods defined elsewhere in separate static classes. (Hence the name – they are a way of extending the behaviour of other classes or interfaces) And the reason why they can deal with null objects is that their code takes the object in question as a parameter. The definition looks like:

public static class Extensions
{
  public static void DoSomething(this Widget widget)
  {
    // do something with the widget
  }
}

The this keyword is marking the declaration out as an extension method. And hence the compiler is transforming the original widget.DoSomething() statement into a static method call Extensions.DoSomething(widget) behind the scenes. Hence when widget is null, you don’t get a crash unless the code inside your extension method does something that causes it.

The most commonly used extension methods are probably those provided by the Linq framework to do things like add filtering behaviour to all enumerables. But the other common pattern I see (and the source of confusion for the dev I was talking to) is helping to standardise behaviour for handling parameter or object validation. Things like:

public static class ExampleExtensions
{
  public static void CheckParameterForNull<T>(this T obj, string parameterName) where T : class
  {
    if(obj == null)
    {
      throw new ArgumentNullException(parameterName);
    }
  }
  public static bool IsNullOrWhiteSpace(this string str)
  {
    return string.IsNullOrWhiteSpace(str);
  }
}

public class MyClass
{
  public void MyMethod(Widget widget, string text)
  {
    widget.CheckParameterForNull("obj");

    if(text.IsNullOrWhiteSpace())
    {
      // do stuff
    }

    // do the rest of the method
  }
}

As the question which started me thinking about this suggests, you need to be a bit careful applying this pattern though. Because the idea of “calling a method on a null object” is normally an error pattern in .Net (and many other languages) it’s important to balance the confusion this might cause against whatever benefits the extension method itself can provide. The long term benefits of clear and readable code can outweigh the short term benefit of a clever pattern.

You also have to be a bit careful about the namespaces of your extension methods. You only get intellisense for them (and the code will only compile) if the namespace you declare the static extension class in is included in your current scope – most likely via a using statement. Another source of confusion to up and coming developers is when they start a new file for a class and suddenly a collection of methods on the objects they’re working with have “disappeared”. While it’s a simple fix to reference the correct namespaces, it can be frustrating if the extension classes are defined in unintuitive places in the codebase.

What was it Spiderman said about power and responsibility?

Advertisements

3 thoughts on “When is a reference to null not a null reference?

  1. Nice article in .net 101 šŸ˜€ – Another example I have had to try and get across is when looking at setting parameters objects to null.

    public void SetObjectToNull(IMyObject myObject)
    {
    myObject = null;
    }

    public void SetRefObjectToNull(ref IMyObject myObject)
    {
    myObject = null;
    }

    public void Main()
    {
    IMyObject myObject = new MyObject();
    SetObjectToNull(myObject);
    // myObject will not be null here
    SetRefObjectToNull(ref myObject);
    // but will be here
    }

    • If I was going to start a series on “common mistakes people make when changing to C# from other programming languages” your suggestion would definitely be in there. The difference between pass-by-reference and pass-by-value can be confusing to new devs who’ve grown up in a world where you never really encounter pointers any more. Though to be honest I’m pretty happy that I never encounter C code where you find “pointer to a pointer to a pointer to an int” as a pass-by-reference parameter these days – stuff like that could really ruin your Monday morning šŸ˜‰

  2. Pingback: A thought experiment in text parsing | Jeremy Davis

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s