25

Question

I'd like to have a class that is able to handle a null reference of itself. How can I do this? Extension methods are the only way I can think to do this but thought I'd ask in case there was some nifty thing I didn't know about C#.

Example

I have a class called User with a property called IsAuthorized.

When User is properly instantiated IsAuthorized has an implementation. However, when my User reference contains null I'd like a call to IsAuthorized to return false instead of exploding.


Solution

Lot's of good answers. I ended up using three of them to solve my problem.

  1. I used the Null Object design pattern suggested by Zaid Masud.
  2. I combined that with Belmiris' suggestion of using struct so I couldn't have a null reference
  3. And got a great explanation for why C# works this way and how I could really solve it from Jon Hanna

Unfortunately I can only pick one of these as my accepted answer so if you are visiting this page you should take the time to up vote all three of these and any of the other excellent answers that were given.

Mark Rucker
  • 6,952
  • 4
  • 39
  • 65
  • Just the act of calling `isAuthorized` wouldn't work- it's like trying to find north on a blank compass. – David B Aug 15 '12 at 15:33
  • I know it doesn't work in the conventional sense but there is no reason C# couldn't provide syntax that would support this. – Mark Rucker Aug 15 '12 at 15:34
  • Hope this helps. http://stackoverflow.com/questions/1943465/avoiding-null-reference-exceptions – Chaitanya Aug 15 '12 at 15:36
  • @MarkRucker if you don't have a user (user is null), why would it be Authorized? IMHO, it makes no sense to check if the user is authorized if it is null, the methods shouldn't even be called in these cases – JSBach Aug 15 '12 at 15:45
  • 4
    Question feels like recipie for disaster - if your code decides what caller would have wanted if they initialized User properly why not to decide on whole program behavior in advance - no need to write anything at all. (I read you your question as "contract requirs to initialize all User references, but if someone violated contract I want to respect it and act as if they did initialize it", could be wrong)? – Alexei Levenkov Aug 15 '12 at 16:00
  • @Alexei good point. It made sense in my head to implement it this way but now that you bring up this point I need to think about it some more. – Mark Rucker Aug 15 '12 at 16:04
  • 3
    @AlexeiLevenkov Your code doesn't decide what the caller would have wanted, it decides what the caller is going to get. Most of the time we work to make that as close to what the caller wants as possible, but "I don't have the information needed to construct a user object, please consider me authorised anyway" is a classic example where what the caller wants, and what we're going to give it, does not match! – Jon Hanna Aug 15 '12 at 16:29
  • @JonHanna, Yes, this is just another way to read it (btw, +1 to question as it is interesting by itself as generic question). I would prefer to use "Null object" pattern for such case as mentioned in one of the answers: library code unfortunately have no way to distinguish "I don't have enough info, give me default behavior" and "I totally forget to initialize the variable" cases by simply looking at `null`, so essentially library would make random guess on callers intent. – Alexei Levenkov Aug 15 '12 at 17:02
  • 1
    I do this in a sense with a static helper class. Basically, HelperClass.CurrentUser is a property that returns the logged in user's User object, but if it is null it returns a default(User) which is not null, but a newly instantiated User object where the default value for IsAuthorized is false. For my purposes, this simplifies my authorization code such that I don't have to check if something is null, if it is then I know the user is not authorized and no more code is run that would utilize this object. – Chris Aug 15 '12 at 19:06

7 Answers7

29

How about a proper Object Oriented solution? This is exactly what the Null Object design pattern is for.

You could extract an IUser interface, have your User object implement this interface, and then create a NullUser object (that also implements IUser) and always returns false on the IsAuthorized property.

Now, modify the consuming code to depend on IUser rather than User. The client code will no longer need a null check.

Code sample below:

public interface IUser
{
    // ... other required User method/property signatures

    bool IsAuthorized { get; }
}

public class User : IUser
{
    // other method/property implementations

    public bool IsAuthorized
    {
        get { // implementation logic here }
    }
}

public class NullUser : IUser
{
    public bool IsAuthorized
    {
        get { return false; }
    }
}

Now, your code will return an IUser rather than a User and client code will only depend on IUser:

public IUser GetUser()
{
    if (condition)
    {
        return new NullUser(); // never return null anymore, replace with NullUser instead
    }
    return new User(...);
}
Zaid Masud
  • 13,225
  • 9
  • 67
  • 88
  • Another great idea. Similar to the struct answer but with a fancy design pattern name to go with it. Unfortunately you can't overload reference type default values see http://stackoverflow.com/q/4066315/1066291. So perhaps the best answer is a marrying of the two. I can create a const NullObject that is set to the default struct value and overload the == operator so I can compare my NullObject to my reference when I need to handle the null cases. – Mark Rucker Aug 15 '12 at 15:46
  • 1
    @MarkRucker you do not need to overload reference type default values. I've added a code sample to clarify this solution. – Zaid Masud Aug 15 '12 at 15:59
  • 4
    Be careful with using Null Object. If you do use it, you should use it universally. And, it doesn't prevent all situations in which you must check to see if your reference is really valid; while it avoids exceptions, doing so can hide bugs, masking the real problem behind a failure in some completely different area of the system. – KeithS Aug 15 '12 at 18:53
  • 2
    +1 for a solution that both solves the problem and stays compatible with good practices – PPC Aug 15 '12 at 19:36
  • @KeithS thanks for this "insight", but I think your comment is quite general and not supported by much fact or example ... do you have any references or examples to support this? Specifically that Null Object can "mask the real problem behind a failure"? Also what advantages, if any, are there in using it universally? – Zaid Masud Aug 16 '12 at 16:48
  • It's quite simple: use of the Null Object pattern to define an instance of a reference type that represents "no data" doesn't mean that a reference can't still be `null`. `null` is built into .NET (and most other languages); Null Object isn't. So, in any case where you cannot personally guarantee that a return value from a method will always be valid and can never be `null`, best practice is still to check for `null` and convert any null references to instances of the Null Object. – KeithS Sep 18 '12 at 15:51
  • A common example of the problems "Null Object" can cause if used inconsistently is a null string versus an empty string. A null string is `null`; `String.Empty` is a valid reference to a zero-length string. You can call an instance method, like Clone, CompareTo, StartsWith, etc on an empty string but not null. .NET and third-party OSS coders differ on whether a method will return null or empty, sometimes in similar situations. So, you typically have to expect both, and convert one to the other so you end up with a consistent representation of "no data" in your own codebase. – KeithS Sep 18 '12 at 16:02
  • As far as hiding bugs, Fowler says to "fail fast"; if there's a problem in the code that you are not expecting, the program should tell you as soon as it knows. Null Objects don't necessarily do this; in fact, by being valid to work with (and thus not throwing NullReferenceExceptions when you try to use them), your code can continue for some time, "using" the Null Object, until it encounters a situation where the "output" of your Null Object makes something else invalid. That causes an error much deeper and further away in the codebase than where the real problem may be. – KeithS Sep 18 '12 at 16:06
  • Lastly, you still have to check *something* to determine the object reference you have is valid. Whether it's `myObject == null` or `myObject.IsNullObject`, whether a method call on your object returns a NullReferenceException (because you called it on `null`) or an InvalidOperationException (because you called it on the Null Object), you rarely if ever save code using Null Object over simply checking for null). You still have to ensure your instance is valid and so it will produce the behavior you expect. – KeithS Sep 18 '12 at 16:13
  • 1
    @KeithS thanks, I'll consider your points in some more detail. The key thing we need to understand is that the Null Object is *not* intended as a replacement for an invalid state. It is meant as a return type for a valid, expected condition. You should still return null for invalid conditions and null object for expected conditions. So you aren't violating Fowler's principles; in fact, Fowler calls null object [a very useful refactoring](http://martinfowler.com/bliki/refactoring.html). He also refers to it in the [Special Case pattern](http://martinfowler.com/eaaCatalog/specialCase.html). – Zaid Masud Sep 18 '12 at 16:23
18

However, when my User reference contains null I'd like IsAuthorized to always return false instead of exploding.

This can only be done if IsAuthorized is a static method, in which case you can check for null. This is why extension methods can do this - they are really just a different syntax for calling a static method.

Calling a method or property, such as IsAuthorized as an instance method requires an instance. Just the act of calling an instance method (including a property getter) on null will trigger the exception. The exception isn't raised by your class, but by the runtime itself when you attempt to use the (null) reference. There is no way around this in C#.

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
  • I'm interested in how this would be done with a static method. Can you provide an example? – David B Aug 15 '12 at 15:33
  • Right, I understand why extension methods support this. I just thought I'd ask in case there was another way. It can be confusing when I go to the reference of a method and go to my extension methods instead of the actual implementation. – Mark Rucker Aug 15 '12 at 15:33
  • 2
    static bool IsAuthorized(User user) { if (user==null) return false; else return user.IsAuthorized(); // The instance method.} Then call it as User.IsAuthorized(currentUser); – Chris Cudmore Aug 15 '12 at 15:33
  • @MarkRucker As static method would look like `User.IsAuthorized(theUser);` This lets you check for null in the implementation (Declaration of `public static bool IsAuthorized(User user)`) – Reed Copsey Aug 15 '12 at 15:35
  • Static methods are called using the class directly, so you would call User.IsAuthorized(user). You would have to send the user object as a parameter – JSBach Aug 15 '12 at 15:35
  • Thanks for the examples- I thought there might be away you could check based on whether it was called by an instance or by class (if that was even possible). I guess not. – David B Aug 15 '12 at 15:39
  • @DavidB The problem is that the exception is raised before your code is called (when using an instance method), since there is no instance on which to call it. Extension methods only work because they're really just static methods rewritten by the compiler. – Reed Copsey Aug 15 '12 at 15:45
  • 2
    A proper extension method would resemble the following: `public static bool IsAuthorized(this IUser user){ if (user == null) return false; else return user.IsAuthorized; }` – IAbstract Aug 15 '12 at 16:17
  • @IAbstract There's no particular reason to introduce an interface here, though- the extension method could work on User directly. Also, if `user.IsAuthorized` exists, the extension method will never get called, so you'll still get the null ref exception. – Reed Copsey Aug 15 '12 at 16:18
  • To give an additional example that many people know. The `String` class offers a method `IsNullOrEmpty` to check a string. They had to make that a static method. Therefore you call it like `string.IsNullOrEmpty(strReferenceToCheck)`. Entirely similar to Reed Copsey's example. – Jeppe Stig Nielsen Aug 15 '12 at 18:24
  • @ReedCopsey You need to do something so that the class's `IsAuthorized` does not override the extension method. My default option is normally an opposite extension method of `IsNotAuthorised`, though in this case a simple `IsAuthorisedUser` would probably do. – Mark Hurd Aug 16 '12 at 09:33
  • The problem with extension methods, is if you are writing the calling code but not the class, and if the method does accept being called on null instances, you have to duplicate what it does in that case, which you may not know. A helper-delegate to you call the method on null objects is more complicated, but lets you access the real behaviour rather than one of your own. – Jon Hanna Aug 16 '12 at 09:53
11

If the variable is null, it means it references no object, therefore is makes no sense (and I think its not technically possible) to handle the null reference inside the class method.

You should guarantee that it is not null, either by checking just before calling "IsAuthorized" or event before.

Edit: Finding an workaround to do that would be a bad thing: it would be confusing for someone to understand the behavior, since it is not the "expected" behavior for the programming language. It could also cause your code to hide some problem (a null value where it should be an object) and create a bug that will be hard to find. That said: it is for sure a bad idea.

JSBach
  • 4,679
  • 8
  • 51
  • 98
  • 3
    Sure it's technically possible, you just need to stretch the definition of "C#" to include calls to `Reflection.Emit` written in C#. – Jon Hanna Aug 15 '12 at 16:24
  • Could you please detail your comment? How would you make a non-static method execute when the variable references no object? – JSBach Aug 15 '12 at 16:31
  • 2
    As per my answer. .NET already supports it (just don't reference any fields or virtual methods within the method if `this == null`), but C# doesn't let you call it. Add a caller written in something else, of which emitting IL is the least-friendly overall, but one you can do from within C# – Jon Hanna Aug 15 '12 at 16:39
7

The problem isn't with creating such a method at all. It's with calling the method. If you put a test of if(this == null) in your code, that's perfectly valid. I suppose it could be optimised away by the compiler on the basis of it being "impossible" to be hit, but I thankfully it isn't.

However, when you call the method, it'll be done via callvirt, so rather than call the method directly, it will find the version of the method to call for the particular instance just as it would with a virtual method. Since that will fail for null references, your perfectly good self-null-testing method will fail before it is even called.

C# deliberately does this. According to Eric Gunnerson this was because they thought letting you do so would be a bit weird.

I've never understood why letting a .NET language modelled upon C++ do something that is perfectly allowable in both .NET and the C++ compiler produced by the same company,* was considered a bit weird. I've always considered it a bit weird that it wasn't allowed.

You can add something from another language (F# or IL) that calls the class, or use Reflection.Emit to generate a delegate that does so and that'll work fine. For example, the following code will call the version of GetHashCode defined in object (that is, even if GetHashCode was overridden, this doesn't call the override) which is an example of a method that is safe to call on a null instance:

DynamicMethod dynM = new DynamicMethod(string.Empty, typeof(int), new Type[]{typeof(object)}, typeof(object));
ILGenerator ilGen = dynM.GetILGenerator(7);
ilGen.Emit(OpCodes.Ldarg_0);
ilGen.Emit(OpCodes.Call, typeof(object).GetMethod("GetHashCode"));
ilGen.Emit(OpCodes.Ret);
Func<object, int> RootHashCode = (Func<object, int>)dynM.CreateDelegate(typeof(Func<object, int>));
Console.WriteLine(RootHashCode(null));

The one good thing about this, is that you can hold onto RootHashCode so you only need to build it once (say in a static constructor) and then you can use it repeatedly.

This of course is of no value in letting other code call your method through a null reference, for that extension methods like you suggest are your only bet.

It's also worth noting of course, that if you are writing in a language that doesn't have this quirk of C#, that you should offer some alternative means of getting the "default" result for calling on a null reference because C# people can't get it. Much like C# people should avoid case-only differences between public names because some languages can't deal with that.

Edit: A full example of your question's IsAuthorized being called, since votes suggest some people don't believe it can be done (!)

using System;
using System.Reflection.Emit;
using System.Security;

/*We need to either have User allow partially-trusted
 callers, or we need to have Program be fully-trusted.
 The former is the quicker to do, though the latter is
 more likely to be what one would want for real*/ 
[assembly:AllowPartiallyTrustedCallers]

namespace AllowCallsOnNull
{
  public class User
  {
    public bool IsAuthorized
    {
      get
      {
        //Perverse because someone writing in C# should be expected to be friendly to
        //C#! This though doesn't apply to someone writing in another language who may
        //not know C# has difficulties calling this.
        //Still, don't do this:
        if(this == null)
        {
          Console.Error.WriteLine("I don't exist!");
          return false;
        }
        /*Real code to work out if the user is authorised
        would go here. We're just going to return true
        to demonstrate the point*/
        Console.Error.WriteLine("I'm a real boy! I mean, user!");
        return true;
      }
    }
  }
  class Program
  {
    public static void Main(string[] args)
    {
      //Set-up the helper that calls IsAuthorized on a
      //User, that may be null.
      DynamicMethod dynM = new DynamicMethod(string.Empty, typeof(bool), new Type[]{typeof(User)}, typeof(object));
      ILGenerator ilGen = dynM.GetILGenerator(7);
      ilGen.Emit(OpCodes.Ldarg_0);
      ilGen.Emit(OpCodes.Call, typeof(User).GetProperty("IsAuthorized").GetGetMethod());
      ilGen.Emit(OpCodes.Ret);
      Func<User, bool> CheckAuthorized = (Func<User, bool>)dynM.CreateDelegate(typeof(Func<User, bool>));

      //Now call it, first on null, then on an object
      Console.WriteLine(CheckAuthorized(null));    //false
      Console.WriteLine(CheckAuthorized(new User()));//true
      //Wait for input so the user will actually see this.
      Console.ReadKey(true);
    }
  }
}

Oh, and a real-life practical concern in this. The good thing about C#'s behaviour is that it causes fail-fast on calls on null-references that would fail anyway because they access a field or virtual somewhere in the middle. This means we don't have to worry about whether we're in a null instance when writing calls. If however you want to be bullet-proof in a fully public method (that is, a public method of a public class), then you can't depend on this. If it's vital that step 1 of a method is always followed by step 2, and step 2 would only fail if called on a null instance, then there should be a self-null check. This is rarely going to happen, but it could cause bugs for non-C# users that you'll never be able to reproduce in C# without using the above technique.

*Though, that is specific to their compiler - it's undefined per the C++ standard IIRC.

Jon Hanna
  • 110,372
  • 10
  • 146
  • 251
  • Even though you can technically be correct, personally I would be really confused to work with the code that use `Emit` for calling things on `null`s. – oleksii Aug 15 '12 at 17:17
  • @oleksii, yes, but you're not going to do that, you're going to do this once and then call `RootHashCode(obj)` from then on. Besides, it is the only way C# can deal with a safe-for-null instance method, so if you have to call one, you've no choice in the matter. But yes, it's not nice - precisely why I say at the end that people writing safe-for-null methods should provide another way to get the same result, so C# callers can use that instead. – Jon Hanna Aug 15 '12 at 17:20
  • @oleksii it also serves to demonstrate the rest of the post. If I was wrong in what I said about it being a matter of C# not letting you call such methods, rather than of such methods not being possible, then the code given wouldn't work. – Jon Hanna Aug 15 '12 at 17:23
  • Yeah, I remember Jon Skeet was saying this in his book. There is quite a few things limited by the C# language, that IL code does allow. It's just I never had a need to work with such code. To a humble guy like me this code will look like a brainf%$k language :) – oleksii Aug 15 '12 at 17:28
  • @oleksii The glory of encapsulation. Write the horrid thing once, test it, and then never look at it again even if you use it a hundred times! But no, it won't come up much (also, there is an actual language called brainf**k btw) – Jon Hanna Aug 15 '12 at 17:36
  • @oleksii `++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.` - "Hello World" in Brainf**k. Things can always get worse ;) – Jon Hanna Aug 15 '12 at 21:12
  • Excellent explanation. Thank you for the detail. +1. I ended up selecting Zaid's as my accepted solution simply because it is closest to what I ended up doing. If I could pick more than one your answer would be next. – Mark Rucker Aug 16 '12 at 12:27
  • The best choice. The null-object approach doesn't answer the literal question but does give a good way of solving the actual problem, while my answer is the opposite (the work is all on the caller's side). – Jon Hanna Aug 16 '12 at 12:53
5

Can you use a struct instead? Then it should not ever be null.

Belmiris
  • 2,741
  • 3
  • 25
  • 29
  • Nice thinking. Is there a way to overload the struct default value? A quick google didn't show any obvious ways to do it. Here's what I found http://msdn.microsoft.com/en-us/library/aa664475(v=vs.71).aspx – Mark Rucker Aug 15 '12 at 15:42
  • @MarkRucker what about setting the value in the struct constructor? – Zaid Masud Aug 15 '12 at 15:51
  • I would just make the default value the invalid value. – Belmiris Aug 15 '12 at 16:03
  • 1
    A struct's default values of fields are always null/zero/false. So you could have a boolean flag that you check and if it's false you're in the null struct, otherwise always set to true. – Random832 Aug 15 '12 at 19:18
  • 1
    That struct's default to all-zeros is one of their strengths. If you're in a situation where it doesn't seem like a strength, it's a good sign you're not in a situation where you shouldn't be using struct :) – Jon Hanna Aug 16 '12 at 12:54
3

You can't reference a property if you do not have a valid instance reference. If you want to be able to reference a property even with a null reference and not put the onus of null-checking on the caller, one way is a static method in User:

static bool IsAuthorized(User user)
{
    if(user!=null)
    {
        return user.IsAuthorized;
    }
    else
    {
        return false;
    }
}

Then, when you want to check your authorization, instead of:

if(thisUser.IsAuthorized)

Do:

if(User.IsAuthorized(thisUser))

Omaha
  • 2,262
  • 15
  • 18
  • This is exactly what I've imagined, but instead of writing this it is better to check in the calling method if the User object is null and if it is null return false if not it can be business as usual. – Chaitanya Aug 15 '12 at 15:43
  • If you are creating such a static method, better to make it an extension method instead. – Zaid Masud Aug 28 '12 at 10:47
2

The only way this can work is if you use an extension method or other static method to handle the null reference.

NullReferenceExceptions (NullPointerExceptions for the Javaheads; roughly synonymous) occur when code is told to call a method belonging to an object instance that doesn't actually exist. The thing you must keep in mind is that null is not actually any object. A variable of a type can be set to null, but that simply means the variable doesn't reference an instance.

Therein lies the problem; if a variable, regardless of its type (as long as that's a nullable type), is null, then there isn't an instance on which to call the method, and an instance is required for instance methods because that's how the program determines the state of members accessible to the method. If MyClass had a MyField and MyMethod(), and you called MyMethod on a null reference of MyClass, what's the value of MyField?

The solution is usually to move to static scope. Static members (and classes) are guaranteed to have state because they are instantiated once at runtime (usually just-in-time, as in before first reference). Because they always have state, they can always be called and so can be given things to do that may not be able to be done at the instance level. Here's a method you can use in C# to return a value from an object member chain which may otherwise result in an NRE:

public static TOut ValueOrDefault<TIn, TOut>(this TIn input, Func<TIn, TOut> projection, 
       TOut defaultValue = default(TOut))
    {
        try
        {
            var result = projection(input);
            if (result == null) result = defaultValue;
            return result;
        }
        catch (NullReferenceException) //most nulls result in one of these.
        {
            return defaultValue;
        }
        catch (InvalidOperationException) //Nullable<T>s with no value throw these
        {
            return defaultValue;
        }
    }

Usage:

class MyClass {public MyClass2 MyField;}
class MyClass2 {public List<string> MyItems; public int? MyNullableField;}

...
var myClass = null;
//returns 0; myClass is null
var result = myClass.ValueOrDefault(x=>x.MyField.MyItems.Count);
myClass = new MyClass();
//returns 0; MyField is null
result = myClass.ValueOrDefault(x=>x.MyField.MyItems.Count);
myClass.MyField = new MyClass2();
//returns 0; MyItems is null
result = myClass.ValueOrDefault(x=>x.MyField.MyItems.Count);
myClass.MyField.MyItems = new List<string>();
//returns 0, but now that's the actual result of the Count property; 
//the entire chain is valid
result = myClass.ValueOrDefault(x=>x.MyField.MyItems.Count);
//returns null, because FirstOrDefault() returns null
var myString = myClass.ValueOrDefault(x=>x.MyField.MyItems.FirstOrDefault());
myClass.MyField.MyItems.Add("A string");
//returns "A string"
myString = myClass.ValueOrDefault(x=>x.MyField.MyItems.FirstOrDefault());
//returns 0, because MyNullableField is null; the exception caught here is not an NRE,
//but an InvalidOperationException
var myValue = myClass.ValueOrDefault(x=>x.MyField.MyNullableField.Value);

While this method has value in situations which would otherwise call for long nested ternary operators to produce something (anything) to show the user or use in a calculation, I do NOT recommend using this pattern to perform actions (void methods). Because no NREs or IOEs will be thrown out, you'll never know if what you asked it to do was actually done. You may be able to get away with a "TryPerformAction()" method which returns true or false, and/or has an output parameter containing the thrown exception (if any). But if you're going to go to that kind of trouble, why not just try/catch the thing yourself?

KeithS
  • 70,210
  • 21
  • 112
  • 164