I suggest you ...

Add non-nullable reference types in C#

Non-nullability checks have to be manually encoded hundreds of times in any large real-world project, and they are not compile-time-enforced. There are code contracts in .Net 4.0, but their usage is still very verbose, and only partly compile-time-enforced.

What I wish is a pendant to the null-lifting operator ?, for instance, !, so that one could write:
void MyMethod(string! s){ /* s cannot be null :) */}

Or, the way ReSharper does it:
void MyMethod([NotNull] string s){ /* s cannot be null :) */}

5,106 votes
Vote
Sign in
Check!
(thinking…)
Reset
or sign in with
  • facebook
  • google
    Password icon
    I agree to the terms of service
    Signed in as (Sign out)
    You have left! (?) (thinking…)
    Marc SigristMarc Sigrist shared this idea  ·   ·  Flag idea as inappropriate…  ·  Admin →

    90 comments

    Sign in
    Check!
    (thinking…)
    Reset
    or sign in with
    • facebook
    • google
      Password icon
      I agree to the terms of service
      Signed in as (Sign out)
      Submitting...
      • Anonymous commented  ·   ·  Flag as inappropriate

        @Kris: you can see it like the feature in C++, where you can have arrays of (and use dynamic_cast with) pointers, but not references [which bear some resemblance to nullable and non-nullable reference types in C#].

      • Anonymous commented  ·   ·  Flag as inappropriate

        @Kris: the question boils down to implementation of default(T) for a non-nullable T.

        My personal opinion would be making it just illegal, so it wouldn't be possible to have an array of C!'s. So, as a direct answer to your question, this shouldn't be compilable.

        This would make an unpleasant difference between "natively" non-nullable value types and nullable reference types, however I don't see any better solution.

        Interesting is, how is this implemented in Comega (http://research.microsoft.com/en-us/um/cambridge/projects/comega/)?

      • Kris VandermottenKris Vandermotten commented  ·   ·  Flag as inappropriate

        Dean G, your NonNullable<T> value type is, unfortunately, very nullable.

        For example:

        NonNullable<string> s = default(NonNullable<string>);

        Or

        NonNullable<string> s = (new NonNullable<string>[10])[0];

      • Kris VandermottenKris Vandermotten commented  ·   ·  Flag as inappropriate

        I would vote for this, if someone can tell me what the value of v should be after executing this code, given class C { }:

        C![] items = new C![10];

        C! v = items[0];

        Or the value of v2, given class D : C { }:

        D! v2 = v as D!

      • PeterPeter commented  ·   ·  Flag as inappropriate

        This would be by far my #1 feature request for C# / .NET. It would eliminate so many headaches and so much work. I don't know what is the best way to solve this problem, but if the .NET team would be willing to sacrifice backwards compatibility in the name of fixing this problem, I think it would instill a feeling that the platform is moving forward and willing to fix mistakes and not just accumulate them.

        So guys, please fix this and make it such a high priority that you would be willing to break things to save effort in the future.

        Whatever feature you come up with in the future, it would pale in comparison to the benefits of having nulls eliminated by the compiler. Thanks.

      • Dean GDean G commented  ·   ·  Flag as inappropriate

        It is a great idea. Not sure where I got this code from, but this is what I've had to do in the mean time:

        ///<summary>A simple structure to wrap a class reference after ensuring that the reference is not null.</summary>
        public struct NonNullable<T> where T : new()
        {
        /// <summary>Check and wrap a value.</summary>
        /// <param name = "aItem">The value to check and wrap.</param>
        /// <exception cref="System.ArgumentNullException">If Value is a null reference.</exception>
        /// <remarks>To pass a non null value use ?? operator.</remarks>
        public NonNullable(T aItem)
        {
        if (aItem == null)
        {
        mValue = new T();
        // throw (new System.ArgumentNullException("value", "That value is null"));
        }
        else
        {
        mValue = aItem;
        }
        //return;
        }

        ///<summary>Get a String representation of the wrapped value.</summary>
        ///<returns>The result of the wrapped value's ToString().</returns>
        public override string ToString()
        {
        return (this.Value.ToString());
        }

        ///<summary>Implicit wrapping of the value.</summary>
        ///<returns>The wrapped value.</returns>
        ///<exception cref="System.ArgumentNullException">If Value is a null reference.</exception>
        public static implicit operator NonNullable<T>(T aItem)
        {
        return (new NonNullable<T>(aItem));
        }

        ///<summary>Implicit unwrapping of the value.</summary>
        ///<returns>The unwrapped value.</returns>
        public static implicit operator T(NonNullable<T> aItem)
        {
        return (aItem.Value);
        }

        /// <summary>The wrapped value.</summary>
        public T Value
        {
        get { return mValue; }
        private set { mValue = value; }
        }
        T mValue;
        }

      • Marc SigristMarc Sigrist commented  ·   ·  Flag as inappropriate

        @Vladislav: Yes, non-nullable reference types would make C# more "symmetric" (with nullable value types), which is in itself a good thing from a language design perspective.

      • Anonymous commented  ·   ·  Flag as inappropriate
      • Anonymous commented  ·   ·  Flag as inappropriate

        @Marc: Well, I don't think this brings too much of additional complexity into the language. On the contrary, it makes the type system simpler: with your suggestion, both reference and value types can be either nullable or not. As of now, only value types have a choice.

      • Marc SigristMarc Sigrist commented  ·   ·  Flag as inappropriate

        As my suggestion has become somewhat popular, I would like to add more context to it. Null references were introduced in ALGOL in 1965. The language designer has famously described this as his "billion dollar mistake" (see
        http://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare).

        The error has been copied by the mainstream OO languages, inclusign C#. By now, the worldwide costs of preventing and fixing NullReferenceExceptions might easily be in the range of a billion dollars a year.

        Given the seriousness of the problem, the correct thing to do would be to redesign C# (or even the .Net Framework) so that, by default, the usage of null is forbidden. To indicate that something might or might not exist, a new "Option<T>" or "Maybe<T>" type could be added, ideally with proper syntactical support in the language. An example of a .Net language who works like this is F#.

        However, I don't think it is realistic to expect such a fundamental change in C#, a long-established mainstream language. Therefore, I have suggested the second-best solution, which is to add non-nullable reference types. Of course, this would make C# a bit more complicated, as we would then have four "contingency idioms" (nullable vs. non-nullable value types vs. reference types). But it would still be less complex and expensive than the combined effort of ReSharper/CodeRush, code contracts, coding conventions, documentation, and testing,
        while still running the constant risk of NullReferenceExceptions.

      • PauloPaulo commented  ·   ·  Flag as inappropriate

        I suggested a similar idea but now I am voting for your suggestion as it already has more votes!
        Great idea!!! hehe

      • Anonymous commented  ·   ·  Flag as inappropriate

        @Akash: Well, are the Code Contracts constraints enforced at compile-time? If no, your suggestion doesn't bring too much.

      • Akash KavaAkash Kava commented  ·   ·  Flag as inappropriate

        Use code Contracts, this is a Logical check, not a language feature. Also null May come from anywhere, how do you check?

      • DoomyDoomy commented  ·   ·  Flag as inappropriate

        This feature would be useful when using the Null Object pattern. The idea is that an instance of specific class is used to represent a null state instead of using 'null' itself. Non-nullable reference types would allow a class designer to enforce the use of the null class.

        http://en.wikipedia.org/wiki/Null_object_pattern

      • Anonymous commented  ·   ·  Flag as inappropriate

        Assuming that stack/heap placement isn't a critical consideration/factor, couldn't one do this on their own with a struct via operator overloading instead of a class?

      • Justin MichelJustin Michel commented  ·   ·  Flag as inappropriate

        Akio, take a look at how Kotlin handles null safety...
        http://confluence.jetbrains.net/display/Kotlin/Null-safety

        This means that your "nonnull(s)" scope is implemented simply as "if (s != null)". The language keeps track of whether a particular symbol has already been checked for null.

        They also show how it's possible to add null safety to a large code base without having to rewrite/recompile everything.

      Feedback and Knowledge Base