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 :) */}

1,959 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 →

    59 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...
      • PauloPaulo commented  ·   ·  Flag as inappropriate

        Marian, a struct in C# can always be default initialized, which actually kills the purpose in most cases.
        In C++ it is possible to use a non-pointer class without a default constructor to be the "not null reference"... a class like NotNull<T>. So, in its constructor, it receives a T * but validates it is not null.
        In C# the problem is that a struct can always be default initialized (big mistake, in my opinion) and a reference is, by default, null supporting.

        Notice that the default initialization for value-types and null initialization for references only happens for class fields. Local variables must be initialized in C#, or else you receive a compile time error because you try to use a non-initialized variable. As well, struct fields must be initialized on its constructor... the only problem is the existence of the "automatic default" for structs... which also happens to be valid only when they are used inside classes.

      • Marián ŠpánikMarián Špánik commented  ·   ·  Flag as inappropriate

        One possible solution is to use a structs instead of classes. The struct, as a value type, can't be null. However the struct can't be polymorphic (at least I think so) and you can't store any reference to it anywhere and you have to not forget to pass it as a reference to every function (ref keyword), otherwise you would copy it in each call. Also existing classes can't be used as the structs...
        https://msdn.microsoft.com/en-us/library/ah19swz4.aspx

      • PhylosPhylos commented  ·   ·  Flag as inappropriate

        Perhaps those wanting non-nullable reference types are asking too much from the C# type system. This would be such a fundamental change to C# that one wonders if it's even possible without breaking some fundamental aspects of the type system.

        F# was able to have non-nullable reference types because it was a fundamental part its' type system from the outset, not something bolted on years after the language had been released.

      • Anonymous commented  ·   ·  Flag as inappropriate

        i think we need some giant red buttons labeled

        [help i dont know what im doing]
        and
        [im super lazy auto program for me]

      • Anonymous commented  ·   ·  Flag as inappropriate

        this is so absolutely stupid to me
        i don't understand why this is even needed or for what it is needed

        why not a property guess what... its auto initialized... that's what properties do... try it yourself ....

        to boot this suggestion borders the most fundamental harasy
        the idea of non strict types and no type safety
        whats next [non strict] C1 c;

        hey check it out... how about this ?
        public class A
        {
        string Value{get;set;}
        }

        how do you even say this [NotNull] string value in a parameter
        what if you need to pass null to the value ? you what to change the language because of your particular constructor

        so the compiler has to check parameters for non null so then other people can complain about even slower compiles because were so lazy

        class C2 {
        public C2(string value) { if (value == null) throw new ArgumentNullException("value");
        for(int i = 0; i < 1000; i++) new C1(value);}
        }
        "This clearly shows how strongly reduced performance because of the presence of such verifications"

        are you kidding ? for(int i = 0; i < 1000; i++) new C1(value);}
        first who puts this in there constructor for absolutely no reason

        second you want a [non null] keyword that magically writes this basically
        { if (value == null) throw new ArgumentNullException("value");
        but
        your saying that somehow by magic it will be more performant if the compiler or jit adds the code to infer the check dynamically instead of you typing in that line in your very specific constructor really ?

        my real question
        is were is any real example of any need for this or
        anyone that actually needs this because
        they couldn't simply use a property instead ?

      • MSMS commented  ·   ·  Flag as inappropriate

        Why not a simple and sweet keyword

        void MyMethod(notnull string s)
        {
        ....
        }

      • AsadAsad commented  ·   ·  Flag as inappropriate

        @MauricioScheffer You're misunderstanding the point of non-nullable types if you think option types are an alternative to them. Option types are the necessary complement to non-nullable types, and are used to represent something that may or may not have a value. They're only useful if you can safely assume anything other than an option type will *not* be null.

        In this suggestion, normal reference types are going to be acting as option types, in that we may or may not get a value of the specified type. Adding a bang, however, allows you to specify as part of the compile time contract that you are accepting/returning a non nullable type, which is the logical complement of our default nullable/option types.

      • Pavel Evgenjevich TimoshenkoPavel Evgenjevich Timoshenko commented  ·   ·  Flag as inappropriate

        I propose to consider the following example

        class C1 { public C1(string value) { if (value == null) ... } ...}
        class C2 { public C2(string value) { if (value == null) throw new ArgumentNullException("value");
        for(int i = 0; i < 1000; i++) new C1(value); ...}...}

        This clearly shows how strongly reduced performance because of the presence of such verifications. We could achieve performance benefits due to the fact that the C# has JIT compiler. Consider the following code modification:

        class C1 { public C1([NotNull] string value) { ... } ...}
        class C2 { public C2([NotNull] string value) {
        for(int i = 0; i < 1000; i++) new C1(value); ...}...}

        When compiling attributes are bypassed with code optimization allowing to reduce the number of verifications. I agree with the opinion was expressed that the use of attributes slightly reduces code readability. For this role might be suitable exclamation mark symbol. However, if you look at the scope of attributes, in fact in this case they are more suitable.

        Anyway attributes in C# is very mysterious. On the one hand they are used for storing metadata. On the other hand they miraculous way can do a lot. I for clear language, free from any kind of synthetic hacks. Why in this case does not allow legal use of some useful features of the PostSharp? For example could be given the opportunity to influence the attributes of the compilation process. Made available without any the possibility of realizing hacks validations applied to a piece of code that attribute. Also interesting is the ability to perform actions not only at compile time, but at run time.

        In conclusion, I would like to support the idea of ​​using attributes for partial implementation of code contracts that can be verifiable and optimizable during compilation process. In addition attributes can be customizable:

        [NotNull(exception=typeof(ArgumentNullException)),
        Length(1, 255, message=Properties.Resources.ErrorMessage)] String someValue;

        NotNull:CodeContractAttribute, Length:CodeContractAttribute

      • Johann DirryJohann Dirry commented  ·   ·  Flag as inappropriate

        I believe that it makes lot sense to implement this, because it allows for compiler checking, rather than relying on throwing exceptions. It should work similar to Code Contract's Requires-statement.

        -----------------------
        Method 1 (default):

        void MyMethod(string s)
        {
            if(s == null)
            {
                throw new ArgumentNullException("s");
            }
        // do something...
        }

        Pro:
        * every developer knows it.
        * straighforward to implement

        Con:
        * code will be repeated everywhere
        * checking is in called function, not in calling function

        -----------------------
        Method 2 (bad!):

        If you want it to check only while development, you can use Debug.Assert.

        void MyMethod(string s)
        {
            Debug.Assert(s != null, "Parameter 's' must not be null.");
        // do something...
        }

        Pro:
        * every developer knows it
        * runs a bit faster because no checking in production code

        Con:
        * Code will be repeated
        * Dependency on System.Diagnostics, NUnit, or similar
        * will not check production code

        -----------------------
        Method 3 (perfect):

        Use [Code Contracts].

        void MyMethod(string s)
        {
            Contract.Requires<ArgumentNullException>(s != null, "s");
        // do something...
        }

        Pro:
        * caller must ensure that variable is not null, rather than called method
        * static checking (even before compiling)
        * may be written in a way that minimizes code duplication
        * developer can decide if checking should be done in production code or not using compiler flags

        Con:
        * vew developers understand it
        * implementing static checks are time consuming
        * dependency on CodeContracts when used in production code
        * still a research project, so there is no commitment for its adaptation to new C#/.NET versions.

        -----------------------
        Method 4 (very good):

        Use [PostSharp] ().

        void MyMethod([NotNull] string s)
        {
        // do something...
        }

        Pro:
        * exactly what you want
        * eliminates code duplication
        * you can change what the aspect does by implementing your own
        * no dependencies

        Con:
        * Commercial tool (but usually worth the money)

        [Code Contracts] http://research.microsoft.com/en-us/projects/contracts/
        [PostSharp] http://www.postsharp.net/blog/post/Validating-parameters-field-and-properties-in-PostSharp-3

      • PauloPaulo commented  ·   ·  Flag as inappropriate

        I must say that I see a lot of people saying that we can't have a NonNullable<string> type.
        And I agree. But doing a string! doesn't need to be a real type, only an automatic validation. It can even be a synctatic sugar for a [NotNull]string, which is used by the compiler to do the:
        if (s == null)
        throw new ArgumentNullException("s");

        It will really eliminate lots of duplicated code, will reduce the number of errors caused by people who refactor the parameter names but forget the exception message and things like that.

        In fact, I created a "required" for parameters in POLAR:
        http://www.codeproject.com/Articles/280361/POLAR-Creating-a-Virtual-Machine-in-NET

        So I can guarantee that it works.

      • Martijn HoekstraMartijn Hoekstra commented  ·   ·  Flag as inappropriate

        @Vladislav don't mistake a program with undefined behavior with being not well-formed. It explicitly is allowed in the language specification with undefined behaviour, nothing non-well-formed about it (but a bad idea nonetheless)

      • Anonymous commented  ·   ·  Flag as inappropriate

        @Paulo: Actually, your example is not correct: dereferencing null pointer in C++ is undefined behaviour, the program is not well-formed.

      ← Previous 1 3

      Feedback and Knowledge Base