Friday, April 22, 2011

Extension Methods | Calling Extension Methods on Null References

"Can extension methods be called on a null reference?" That was what I said when I read the following on a post by Marc Gravell's where he says:

(the Step(…) method is implemented as an extension method, so it is perfectly happy operating on a null reference; which is a crude but simple way of short-circuiting the timings for regular users)

To be honest I had never thought about this before... I therefore had to try it out and figure out why!

using System;

namespace ExtensionMethodNullReferenceTest
{
    class Program
    {
        static void Main( string [] args ) {
            ((object)null).SaySomething();
        }
    }

    static class ExtensionMethod
    {
        public static void SaySomething( this object obj ) {
            Console.WriteLine( "Saying something..." );
        }
    }
}

In the example above we have a very simple extension method called SaySomething(). In Main I'm calling that extension method on... well... nothing.

If we remind ourselves that extension methods are not really extending the object, but are simply static methods on a static class, and that they are called as static methods, this makes sense. The object that we appear to be calling the extension method on is just passed as an argument to the static extension method.

The Il produced for the call to the extension method is as follows, the null reference being pushed onto the stack for the first parameter:

call void ExtensionMethodNullReferenceTest.ExtensionMethod::SaySomething(object)

This raises a possibly obvious issue. If we are going to do anything with the object that is passed we need to be careful. The following code will throw a NullReferenceException

using System;

namespace ExtensionMethodNullReferenceTest
{
    class Program
    {
        static void Main( string [] args ) {
            ((object)null).SaySomething();
        }
    }

    static class ExtensionMethod
    {
        public static void SaySomething( this object obj ) {
            Console.WriteLine( obj.ToString() );
        }

    }
}

The error is as follows:

Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object. at ExtensionMethodNullReferenceTest.Program.Main(String[] args) in C:\_Development\Examples\ExtensionMethodNullReferenceTest\ExtensionMethodNullReferenceTest\Program.cs:line 8

Interestingly, in the error I received above, I don't actually get a line number inside the extension method. ( Though when I put another Console.WriteLine() above the first Console.WriteLine() in the extension method I do then get an exception message that tells me the line number within the extension method.)

The main point is that if you are calling an extension method on an object reference that is null and you try and do something with that reference within the extension method, you could get an exception if not careful.

No comments:

Post a Comment