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,869 votes
Sign in
or sign in with
  • facebook
  • google
    Password icon
    Signed in as (Sign out)
    You have left! (?) (thinking…)
    Marc Sigrist shared this idea  ·   ·  Flag idea as inappropriate…  ·  Admin →


    Sign in
    or sign in with
    • facebook
    • google
      Password icon
      Signed in as (Sign out)
      • will motill commented  ·   ·  Flag as inappropriate

        This is basically suggesting that memory be allocated to a reference that potentially is just garbage data this actually would allow others to prevent you from doing a null check on it to find were a problem comes from how would this help anyone ?.

      • will motill commented  ·   ·  Flag as inappropriate

        Btw "Add non-nullable reference types in C#" that would literally be a struct.
        Seriously 4,082 votes to add a struct reference type to c# ?
        Unless 4,082 voters really believe references other then struct's shouldn't need you the programmer to actually give them a value and should be non null if you forget to actually assign a non struct a value ?
        Maybe what is supposed to happen is non structs should use magical energys to divine by supernatural process, Non null and non junk value. Getting these values from beyond the 10th dimension into the non struct Type reference which you forgot to define after declare it, in order to magically initialized it so dat its all ok now ????????<?>?<??...!?>?.

      • will motill commented  ·   ·  Flag as inappropriate

        Was is and even sounds like a bad idea how does this sound.

        Hi im new i have no clue what im doing ya once i wrote a program that made null values i didn't know why but now with non nullable values you can be sure the stuff i give you is not going to crash on the thing that is null. So the junk i send you will run and run then eventually something Else will goof up and crash GG now i feel a lot more pro with non nullable types stuffess :)

      • Jonathan Gilbert commented  ·   ·  Flag as inappropriate

        I think this would have to be implemented as a core runtime feature. In the same way that IL opcodes were added to assist with the new Nullable<T> type in .NET 2.0, what we'd need is a NotNullable<T> struct whose behaviour was special-cased in the CLR.

        This type would have the following properties:

        * It does *not* have a default constructor. Code that attempts to initialize the struct in this way is malformed IL.
        * NotNullable<T> converts to T transparently at the machine code level.
        * Converting T to NotNullable<T> performs a check that the reference is not null. This *could* be done in the C# code implementing NotNullable<T> itself, though we would definitely want the check & conversion to be inlined.
        * To provide support for languages that do not expose any syntactic sugar for it, a public property Value would allow the reference to be extracted as type T.
        * The JIT could omit null reference checks when accessing members of an instance of T via NotNullable<T>, because no valid IL can produce a NotNullable<T> that is a null reference.

        This could then be exposed in languages like C# and VB.NET using a modifier character such as an exclamation point. It would probably make sense for C# to require an explicit cast of T to T!, in keeping with its policy of explicitly showing behaviour. This conversion could, of course, throw a NullReferenceException (in any language).

        Because of the constraint on validity of IL with regards to default initialization of this new struct, compilers targeting the new CLR version would at a minimum need to detect this usage and refuse to compile default(NotNullable<T>) or new NotNullable<T>(). That would be the only change required to be barebones functional with the new type.

      • Frédéric Decréquy commented  ·   ·  Flag as inappropriate

        This is the link to vote to the C sharp contract extension referenced by Felix, in the previous comment for this suggestion : https://visualstudio.uservoice.com/forums/121579-visual-studio-2015/suggestions/3330248-provide-code-constracts-editor-extension-for-vs201

        "Felix commented · May 23, 2016 20:24 · Flag as inappropriate
        Actually, this feature exists in .Net and his name is Code constracts for Visual Studio or C# extension called Spec#. For this validations, it's a best way. I think if you use the CbD's library, your code could be ugly. Then, I suggest add Spec# core into C#.

      • Felix commented  ·   ·  Flag as inappropriate

        Actually, this feature exists in .Net and his name is Code constracts for Visual Studio or C# extension called Spec#. For this validations, it's a best way. I think if you use the CbD's library, your code could be ugly. Then, I suggest add Spec# core into C#.

      • Georgii Kalnytskyi commented  ·   ·  Flag as inappropriate

        Why is the System.Diagnostics.Contracts class not appropriate for this? You might even create a wrapper attribute for using it, I think.

      • RS commented  ·   ·  Flag as inappropriate

        Just my two cents but this seems like a weird request; one, I just hope, it's not seen as a priority.

        The core reason behind this appears to be laziness but, being lazy myself, I believe that there are multiple (and way simpler) approaches to this "problem"; e.g., snippets, T4, the ingenious NonNullable struct, etc. It seems everyone agrees that no suggested solution would be (100%) "safe", so I'm actually amazed of how much energy can go into this.


        P.S. I'm a little surprised by the... "simplicity" of this forum, including the order of the posts --very unfriendly for reading a thread.

      • Nate commented  ·   ·  Flag as inappropriate

        Wish I could edit a past comment...

        But one more thing to note is that System.Nullable<T> has been around since v2, so things like ? and ?. (null-conditional operators) are merely candy to do something the .NET framework has already supported since v2.

        Adding a new wrapper type or functionality to a similar level for something like NonNullable would require more than just a change in the framework, but also to each language that would need to support it (and compiler at that note)...sounds kind of scary for a feature that we've got by without up until now and sounds like it has very little need for.


      • Nate commented  ·   ·  Flag as inappropriate

        I don't know if it helps any, but it's possible to add a couple things that are still obvious to the consumer of the method and the builder:

        1) Add an attribute that you create that accepts the name of the non-nullable argument/parameter, it's job is to have a method that can be run to ensure that any null value passed in for that parameter is cause for an exception.
        2) The above attribute can be run on the fly, but is publicly available for external calls
        3) An automated test OR Roslyn build-check block of code could be added that can run through all methods with this attribute to ensure that nothing is currently passing in as null obviously/statically in code


        public abstract void RunReport(Item param1, Item param2, string extraInformation);

        then, on second thought, if something like this were to be added in, i would imagine a derivative of that that may allow more flexibility could be to extend the conditionals we can add to methods/classes:

        public abstract void RunReport(Item param1, Item param2, string extraInformation) where param1 not Nullable where param2 not Nullable

        1) this would give us more extensability with conditionals (we could now supply conditionals to a property name, rather than just to a type
        2) this would also allow us to provide more functional conditions that apply to more than just build-time, but still could be applied to build-time (beyond generics)

        What this doesn't do:
        1) Prevent a nullable value store for variables within a closure

        Though, if you want to do that kind of defensive programming, either your methods are too large, or you need to supply structs and primatives, instead, because they already have this desired behavior.

        More often than not, it's preferred not to have extra side effects for your methods anyways, aside from the traditional TrySet methods: bool TryUpdateValueToSomething<TOutVal>(...., out TOutVal value);

        You can always have a blocking or check variable that gets the results of your method call, and then only set if it is not null. I know this doesn't help with the monotonous work being done, but I feel hesitant to say that it's common enough to encourage this need by having a change to the language to support it.

        One more thing to note about supporting non nullable as a type specifier rather than just another conditional is that you now open up a can of worms that were never there to begin with. How does your method handle setting values for ref/out? You now have to do what for those values in that scenario? outVar = default(TOutVar); ?...what if default(TOutVar) is null because we are dealing with a class (instead of the primatives and structs that prevent this behavior automatically?)

        I'm concerned that this buys more trouble than it gains unless we limit just to extending conditionals to support run-time checks and apply to more than just Types and prevent the use of the 'out' and 'ref' specifiers when supplying parameters.

        It just starts to sound more and more like UnitTests, Attributes, custom Build-Check rules via Roslyn, and Assertion statements are more and more the way to go with this.


      • Anonymous commented  ·   ·  Flag as inappropriate

        Though i posted the code below for a basic check
        I think most of us can see the dangers that are associated with doing things like this.
        For the receiver getting garbage data of a sender doing this.


      • Anonymous commented  ·   ·  Flag as inappropriate

        So is what is asked for a more robust version of something like below...
        Maybe someone who is really good with reflection could improve this.

        public class myclassb { public myclassb() { } }
        public class myclassc { public myclassc() { } }

        public MyConstructor()
        object a = null;
        myclassb b = new myclassb();
        myclassc c = null;

        // test
        if (TryInstantiateNull(ref a)) { Console.WriteLine(" some if else msg when wraping the a createinstance failure"); }
        if (TryInstantiateNull(ref b)) { };
        if (TryInstantiateNull(ref c)) { };

        bool TryInstantiateNull<T>(ref T a)
        bool result = false;
        Console.Write(" null check ");
        if (a == null)
        result = true;
        Console.Write(" is null!!!");
        T t;
        t = Activator.CreateInstance<T>();
        a = t;
        if (a != null)
        Console.WriteLine(" - is not null ");
        result = false;
        return result;

        /* output
        * null check is null!!! - is not null
        * null check - is not null
        * null check is null!!! - is not null

      • Steve Leigh commented  ·   ·  Flag as inappropriate

        @Philippe: I don't think anyone has said it should be mandatory. See https://github.com/dotnet/roslyn/issues/5032.

        Simply put, I can declare

        Foo? myFoo = new Foo();

        and be guaranteed at compile time that it's not nullable. I can still assign it to a nullable reference type (eg. pass it to DoSomething(Foo foo)), so we can keep all backwards compatibility.

      • Philippe commented  ·   ·  Flag as inappropriate

        Another thing... Now that ?. operator has been added, it would give contrary views of the problem. On one hand we make it easier to write code that handle null and on the other hand, we want to avoid the possibility to have null references.

        Given the wide use of C#, if non null reference is added to the language, I think it should be optional as readonly and other modifiers.

        And also would it be possible to write generic code that works appropriately in both cases? It is already hard to write generic code because it is much less flexible than C++ templates.

        For example, for container that allows to specify an initial size including built-in arrays, what would be the initial value of each item? would default(T!) give a new T? If so the type must support default new. Existing container don't have such restriction and it is not possible to vary those clause depending on the type...

        Or would some member functions have additional restrictions. Maybe such fonctions should then be annotated to indicate that they are only available for type that can be default construct.

        Thus it might be preferable to support metaprogramming first in the language... but then would you want to go as far as C++?

      • Philippe commented  ·   ·  Flag as inappropriate

        While it might be nice to add non-nullable reference, they should not be the default.

        One might argue that it would be the best default. Assuming it was a new language, then probably. At this point, it would be a major breaking change. So much code has been written with that assumption.

        It could be explicit using either ! notation or a NotNull attribute or some "required" modifier.

        Beyond the fact that it would break too much code, another reason why non null reference should not be the default, is for consistency with other features that do not have the best default according to the point of view of what would typically lead to the best design.

        If non null reference would be the default, then readonly, const and pure functions should also be the default...

        On the other hand, if non null reference support is added, then having an attribute (or modifier) that allows it the default on a per type basis might make sense.

        Also, such changes would have impact on generic code. How function like TryGetValue should works? I guess one would have to use a temporary nullable reference in that case and initialize a non null reference from it after ensuring it is not null.

        However, it is not possible to write a function similar to TryGetValue that would works on non nullable types. That is, it would returns false and the compiler would known that the variable should be used only when the function returns true. Thus extra attributes (or even some form of advanced conditionnal code contract) would be required...

      • Paulo Zemek commented  ·   ·  Flag as inappropriate

        Dax, actually you are misunderstanding how it is supposed to work.
        If you have a field that can't be null, it must be initialized or else the construction fails.
        Then, if you try to set null to it is supposed to fail, using reflection or anything else.
        So, there's no need to check for "unchecked" or anything else.
        And, considering .NET doesn't really have a not-null for reference types, it simply means that any method that uses the field, variable etc will start by checking if the value is different than null, throwing an exception if it is null (a different one than NullReferenceException... maybe the ArgumentNullException for input arguments)... yet, the compiler could help by disallowing, at compile-time, passing null constants or expressions known to return null.

      • Dax Fohl commented  ·   ·  Flag as inappropriate

        I don't think this will ever work quite right. You'll parse something using JSON.NET and it'll be null even though it's supposedly not a valid value. This happens with F# records.

        So *then*, rather than just a null check, an "unchecked {if (*x == 0) {}}" check, which is even worse.

        The CLR has nulls, so there's always the chance that one will sneak in where it shouldn't. You'd simply need a different runtime, that doesn't support nulls at all, like Rust, to support this feature correctly.

      • Paulo commented  ·   ·  Flag as inappropriate

        Dag, that struct is useless in C#.
        Anybody can declare a variable like:
        public readonly NotNull<string> ThisIsNeverInitialized;

        As the variable is not initialized, it will contain null.
        You can also initialize it using default(NotNull<string>); and when getting the value, it will be null.

        The problem is the fact that structs have a default!

      • Dag Øystein Johansen commented  ·   ·  Flag as inappropriate

        @paulo You can make a NotNull<T> struct and use it like you described the C++ case:

        public struct NotNull<T> where T: class
        public NonNull(T object)
        if (object == null)
        throw new ArgumentNullException();

        Value = object;

        public T Value { get; set; };

        // elsewhere...

        void foo(NotNull<string> s)
        DoSomething(s.Value.ToUpper()); // s.Value is guaranteed never to be null.

        What is missing here is the argument name. That can be quite important though, and I much prefer the far less typing-intensive analog to the System.Nullable<T> shorthand. The "string!" shorthand would make it as easy to modify existing code (that lacks the argument check) as adding the exclamation mark. The other approach is more cumbersome.

        That said, it seems to me that MS could elect to do this in a way quite similar to what they did with System.Nullable *and* get the parameter name too, since C# 5 has provisions for obtaining the names of parameters.

      Feedback and Knowledge Base