Non-nullable reference types

I suspect this has been done several times before, but on my way home this evening I considered what would be needed for the reverse of nullable value types – non-nullable reference types. I’ve had a play with an initial implementation in MiscUtil (not in the currently released version) and it basically boils down (after removing comments, equality etc) to this:

public struct NonNullable<T> where T : class
{
    private readonly T value;

    public NonNullable(T value)
    {
        if (value == null)
        {
            throw new ArgumentNullException(“value”);
        }
        this.value = value;
    }

    public T Value
    {
        get
        {
            if (value == null)
            {
                throw new NullReferenceException();
            }
            return value;
        }
    }

    public static implicit operator NonNullable<T>(T value)
    {
        return new NonNullable<T>(value);
    }

    public static implicit operator T(NonNullable<T> wrapper)
    {
        return wrapper.Value;
    }
}

Currently I’ve got both conversion operators as implicit, which isn’t quite as safe/obvious as it is with nullable value types, but it does make life simpler. Obviously this is experimental code more than anything else, so I may change my mind later.

The simple use case is something like this (along with testing error cases):

[Test]
public void Demo()
{
    SampleMethod(“hello”); // No problems
    try
    {
        SampleMethod(null);
        Assert.Fail(“Expected exception”);
    }
    catch (ArgumentNullException)
    {
        // Expected
    }
    try
    {
        SampleMethod(new NonNullable<string>());
        Assert.Fail(“Expected exception”);
    }
    catch (NullReferenceException)
    {
        // Expected
    }
}

private static void SampleMethod(NonNullable<string> text)
{
    // Shouldn’t get here with usual conversions, but could do
    // through default construction. The conversion to string
    // will throw an exception anyway, so we’re guaranteed
    // that foo is non-null afterwards.
    string foo = text;
    Assert.IsNotNull(foo);
}

I don’t intend to use this within MiscUtil at the moment. Note that it’s a struct, which has a few implications:

  • It has the same memory footprint as the normal reference type. No GC pressure and no extra dereferencing. This is basically the main reason for making it a struct.
  • It ends up being boxed to a new object. Boo hiss – ideally the boxing conversion would box it to the wrapped reference, and you could “unbox” (not really unboxing, of course) from a non-null reference to an instance of the struct.
  • It’s possible to create instances wrapping null references, by calling the parameterless constructor or using the default value of fields etc. This is very annoying.

The good news is that it’s self-documenting and easy to use – the conversions will happen where required, doing appropriate checking (reasonably cheaply). The bad news is the lack of support from either the CLR (boxing behaviour above) or language (I’d love to specify string! text as the parameter in the sample method above.) I suspect that if Microsoft were to do this properly, they’d want to avoid all of the problems above – but I’m not sure how…

Anyway, just a little experiment, but an interesting one – any thoughts?

25 thoughts on “Non-nullable reference types”

  1. Overall I love this idea. I wish it would get deep Language and CLR integration.

    Throwing a null reference exception seems wrong here. A null reference has not actually occurred. It seems like an InvalidOperationException would be more appropriate.

    Like

  2. Yes, InvalidOperationException would be appropriate. The only downside is that that exception doesn’t really indicate anything to do with nullity. I guess there’s always the message side of things.

    Of course, that kind of thing can be easily tweaked.

    Like

  3. Isn’t the null check in the Value property getter redundant? The only way that value is set as far as I can see is through the constructor, which checks for null.

    Like

  4. I like it.

    Two concerns:

    1. Why does the Value property bother checking for null & throwing? Haven’t you already confirmed non-null in the constructor?

    2. If the implementation of Value is going to be trivial, why bother with a property at all? I’d skip the property, make the field pubilc, and rename it to “Value”.

    Like

  5. Eddie/Jay: This is a struct. The default value (and the result of calling the parameterless constructor) will wrap a null reference.

    Elij: You can’t overload the equal operator – but the implicit conversion will make your code blow up appropriately.

    Jay: Even for trivial values, I prefer properties over public fields. The only time I ever expose public fields is for constants, and even then I’m somewhat leary.

    Like

  6. I wonder how you might use this sort of thing to better facilitate the Null Object pattern. I can see how a static method in an interface might be worthwhile now. I suppose you could use reflection to hack in some kind of duck-typing in order to get at a static factory method that returned a null object reference for the type.

    It’s a shame C# doesn’t have typedefs, done right this pattern could be really slick.

    Like

  7. Neat. I think the problems you’ve listed – that default instances and values returned by the parameterless constructor are null values – make calling the type ‘NonNullable’ a bit optimistic, however.

    But as a way of automating null-checking on a parameter, this is pretty neat, actually, thanks to the implicit conversion operators – has an aspect-oriented flavour to it. Maybe the name should be changed to be more appropriate as a type declaration in an argument list – NotNull perhaps?

    Like

  8. @Drakiula:

    Firstly, you can’t add parameterless constructors to structs. Secondly, that would have no effect anyway, as it would just set value to null (as that’s the default value for all reference types).

    Like

  9. Sorry for double posting, I wanted to post

    public NonNullable()
    {
    this.value = new T();
    }

    Alas, for this to work, the new() generic constraint for T would have to be added.

    Like

  10. @Drakiula:

    There’s still the problem of not being able to specify a parameterless constructor. Also, the constraint is quite a restrictive one and I suspect wouldn’t actually be what you wanted very often. It would also involve creating far too many instances of T for no reason!

    Like

  11. I’m surprised you didn’t mention Spec# or Sing#, both internal variations of C# created by Microsoft. (Singularity, Microsoft’s experimental operating system, is written in Sing#.) IIRC, they both allow you to write, say, , where the “!” specifies that is guaranteed to be non-null. With this declaration in hand, the compiler can (and, I think, does) ensure that nowhere throughout the entire application (including subroutine parameters (suitably declared with !’s themselves)) can’t be null, else you’ll get a compile-time error.

    I’m hoping, verging on expecting, that this (and other Spec# features) will be part of C# 4.0.

    Like

  12. @Larry: Such is the downside of blogging in a relative hurry :)

    I’m not sure that it’s feasible to introduce Spec# compile-time requirements at this point in time – it’s like introducing const-correctness into an existing library. Who’s going to go over all of your code to change all the signatures?

    I don’t *think* any of this is likely to come in C# 4 – which is likely to be a relatively small set of enhancemenets anyway – but there’s certainly stuff the compiler could do to at least enforce constraints at execution time without as having to laboriously write out all the pre/post-condition checking manually. Maybe C# 5…

    Like

  13. I created a similar struct type and have been experimenting with it for almost a year. I love the idea of a self-documenting mechanism for declaring method preconditions, class invariants, etc..

    In hopes of keeping the impact to surrounding code as small as possible, I (like you) made both conversion operators implicit. Unfortunately, without language support, I’ve still found myself forced to think far too frequently about conversions to and from NonNullable. For instance:
    1. Accessing the methods (and properties) of a NonNullable object requires ubiquitous usage of the Value property or an explicit cast. (I quickly gave up on using this for fields and properties.)
    2. Casting from one NonNullable type to another is cumbersome. For instance, if class B derives from class A, then I should be able to substitute a NonNullable wherever the code expects a NonNullable. However, given C#’s lack of support for generic type covariance, I’m once again forced to use an explicit cast to class A.

    Perhaps someone has some suggestions for improving usability around a type like this?

    Like

  14. Hehehe. I asked a very similar question on microsoft.public.dotnet.languages.csharp last year, but I didn’t really get much response. I’ve linked to the post if you click on my name. It’s frustrating that there really no good option at the moment, pick one of: masses of null-checking boilerplate code in all your methods; hard to debug NullReferenceExceptions; clever but awkward semi-kludges such as this.

    Like

  15. John, could you explain in a bit more details why is it worse to specify it as
    public class NonNullable where T : class {} ?

    To avoid referencing an original value we could use Object.MemberwiseClone() in a constructor:

    public NonNullable(T value) {
    if (value == null) {
    throw new ArgumentNullException(“value”);
    }
    this.value = value.MemberwiseClone();
    }

    This would make unnecessary if (value == null) check in a getter.

    Like

  16. Hi Jon,

    thanks for this great little utility class I’m sure it will help us avoid many common errors in our internal libraries in the future.

    There is a problem with your solution however… Since you are using a struct (which you should) you also get a default parameterless constructor that lets a user circumvent the null check in the other constructor. the problem is that you can’t redefine this default constructor via. c# code. So I took the liberty to make a similar implementation where I’ve modified the IL to throw exception if you call the default parameterless constructor, it has also been marked as obsolete (error=true) to have a better design time experience for the developer.

    You can get a copy from:
    http://cid-f61a12f6f7c6dd75.skydrive.live.com/self.aspx/Public/NonNull.zip

    Hope you like it.

    By the way, this is also being discussed on C9:
    http://channel9.msdn.com/forums/Coffeehouse/407089-Non-null-in-C/

    Like

  17. John,

    Nice example of dealing with input requirements.

    However, i think it suffers from one problem: the exceptions that get raised have an “unexpected” stack trace. It wil report the call site (technically) correct as:

    Value cannot be null.
    at TestApp.NotNull`1..ctor(T value) in C:TempNonNullableTestAppTestAppNotNull.cs:line 16
    at TestApp.NotNull`1.op_Implicit(T value) in C:TempNonNullableTestAppTestAppNotNull.cs:line 37
    at TestApp.ReverseNotNullDemo.Run() in C:TempNonNullableTestAppTestAppReverseNotNullDemo.cs:line 13

    However, the upper two lines in the stack trace only confuse the troubled location. The problem exists in the call at line 3. I would like to see:

    Value cannot be null.
    at TestApp.ReverseNotNullDemo.Run() in C:TempNonNullableTestAppTestAppReverseNotNullDemo.cs:line 13

    Now, I’ve used Delphi in an earlier life, and there you could use:

    raise Exception.Create() at $address

    If you had enough information about the call stack, you could trigger the exception at the troubled location, instead of the reporting line.

    Do you think something like that is possible in C# / .Net?

    Like

  18. The NullReferenceException is reserved for use by the CLR (and it’s probably a COM object, to boot). Should not new one up yourself. And I’m 99% sure that you are already aware of that, and this case was just an oversight from something quickly cobbled together.

    Probably should change the thrown exception to:
    throw new InvalidOperationException(“NonNullable<” + typeof(T).Name +”> cannot be null”);

    Like

    1. This was really just a prototype anyway – but where do you believe NullReferenceException is documented to be reserved for use by the CLR? I don’t see any documentation claiming that, nor that it’s a COM object. (It’s visible to COM, but that’s not the same thing.)

      I wouldn’t normally construct a NullReferenceException, but I wouldn’t go so far as to say it’s reserved.

      Like

Leave a comment