I suggest you ...

Add "?." operator to C#

Add the "?." operator to C# and make it chainable like CoffeeScript so we don't have to write null reference checks for every nested property. An example would be:
myObject?.Items?.[0]?.DoSomething()

5,435 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…)
    Jamshid AsadzadehJamshid Asadzadeh shared this idea  ·   ·  Flag idea as inappropriate…  ·  Admin →
    John BevanJohn Bevan shared a merged idea: null-non-coalescing operator  ·   · 
    StephenStephen shared a merged idea: Create a null-safe dereference operator  ·   · 
    Tales AguiarTales Aguiar shared a merged idea: Automaticaly check object nullity before access some member  ·   · 
    completed  ·  Visual Studio TeamAdminVisual Studio Team (Product Team, Microsoft) responded  · 

    The “?.” operator is now implemented in the latest CTP of Visual Studio “14”.

    For links to details about this and other new C# language features, check out this CodePlex post:

    https://roslyn.codeplex.com/discussions/552378

    Please try out the feature, and see how it works for you!

    Thanks again for great input, and the many many votes!

    Mads Torgersen (MSFT)
    C# Language PM

    206 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...
      • mvdnlyrhojmvdnlyrhoj commented  ·   ·  Flag as inappropriate

        Please also implement this globally as a project-level option. If this option were checked then the "." operator would be treated as the "?." operator throughout the project. This option is useful for the programmers who prefer to treat nulls optimistically (that is, only specifically check for nulls in order to throw exceptions, not having exceptions thrown automatically when null objects are accessed) but don't want to litter the code with the "?." operator, and also don't want to spend time with the overhead brought by the null / empty object pattern.

      • verelpodeverelpode commented  ·   ·  Flag as inappropriate

        Another relevant msg I wrote before uservoice:

        The idea of the C# Null Coalescing operator ("??") is great but the current implementation is defective and needs to be fixed, in my opinion. For starters, I will explain problems using "??" in conjunction with "foreach".

        If you jump ahead and say the answer is System.Linq.Enumerable.Empty<T>() then my reply is: I know it exists but it is problematic, as I will explain.

        Firstly, to refresh our memory, note that "foreach" throws NullReferenceException if the collection is null (as opposed to empty non-null). This exception can be avoided in the case of iterating thru the chars of a string as follows:

        void Test(string inText)
        {
        foreach (char ch in inText ?? string.Empty)
        { ... }
        }

        That is great but unfortunately it only works for System.String because System.Array and List<T> do not have an "Empty" property.

        You can use System.Linq.Enumerable.Empty<T>() but it destroys various optimizations in NETFX. Frex:

        void BadArray(int[] inArray)
        {
        foreach (int v in inArray ?? Enumerable.Empty<int>()) {}
        // Compiles to de-optimized form:
        IEnumerator<int> e = ((inArray != null) ? ((IEnumerable<int>)inArray) : Enumerable.Empty<int>()).GetEnumerator();
        ...

        // Whereas:
        foreach (int v in inArray) {}
        // Compiles to optimized form:
        for (int i = 0; i < inArray.Length; i++)
        { int v = inArray[i]; }
        }
        void BadList(List<int> inList)
        {
        foreach (char ch in inList ?? Enumerable.Empty<int>()) {}
        // Compiles to de-optimized form:
        IEnumerator<int> e = ((IEnumerable<int>)(inList ?? Enumerable.Empty<int>())).GetEnumerator();
        ...

        // Whereas:
        foreach (char ch in inList) {}
        // Compiles to optimized form using *struct* Enumerator:
        List<int>.Enumerator e = inList.GetEnumerator();
        ...
        }

        Meaning the Coalesce stops the compiler using the normal optimized iteration of the array. Likewise the Coalesce stops List<T> from using its optimized List<T>.Enumerator *struct* (an inlineable value-type) and forces it to use the general unoptimized non-inlineable version of IEnumerator<int>. Likewise if you use Enumerable.Empty with strings, the normal optimization is killed.

        The following shows one possible and efficient solution that users can implement for arrays:

        // WARNING: This idea is good for arrays but not for List<T>.
        public static class ArrayExtn<T>
        {
        public static readonly T[] Empty = new T[0]; // cached
        }
        void GoodCoalesceArray(int[] inArray)
        {
        // Retains optimized iteration:
        foreach (int v in inArray ?? ArrayExtn<int>.Empty)
        { ... }

        // Test caching:
        int[] emptyA = ArrayExtn<int>.Empty;
        int[] emptyB = ArrayExtn<int>.Empty;
        bool r1 = object.ReferenceEquals(emptyA, emptyB); // true, good.

        // Test immutability of Empty array:
        System.Array.Resize(ref emptyA, 5);
        emptyA[0] = 123;
        bool r2 = object.ReferenceEquals(emptyA, ArrayExtn<int>.Empty); // false, good.
        bool r3 = (ArrayExtn<int>.Empty.Length == 0); // true, still empty, good.
        }

        The above idea works for arrays because zero-length array objects are immutable, unlike List<T>. If we did the same for List<T>, it would have a major defect because you could easily corrupt "ListExtn<T>.Empty" by adding items to the list instance returned by "Empty". As you know, the "readonly" keyword does not stop this kind of corruption.

        List<T>.AsReadOnly() exists but it returns ReadOnlyCollection<T> (instead of List<T>) therefore is incompatible with the desired use of the "??" operator.

        However, as Microsoft, you could create a static List<T>.Empty property that returns an immutable and cached/shared List<T> instance much like how string.Empty behaves.

        Also, for arrays, you could create a static Empty<T>() Method in System.Array (if you cannot create a generic System.Array<T> class containing a Property named "Empty").

      • verelpodeverelpode commented  ·   ·  Flag as inappropriate

        Relevant info I wrote before I saw this on uservoice:

        When the Null Coalescing operator ("??") was added to C#, initially I thought, "Excellent! I will be able to use this convenient new operator in hundreds of places!"

        However, in practise, the result is that I use "??" extremely rarely. I am disappointed by this operator.

        When I was initially thinking "hundreds of places", I was actually thinking of constructions similar to this form:

        void TestFunc(Int64[] data)
        {
        int length;
        if (data != null) length = data.Length;
        else length = 0; // or sometimes -1

        // Alternatively can use "?" but not "??":
        int length = (data != null) ? data.Length : 0;
        }

        Initially I thought I would be able to write:

        int length = data.Length ?? 0;

        But no, it doesn't work like that. The nearest you can do with "??" is the following awkward construction with strings (but not arrays):

        string message = xxxx;
        int length = (message ?? string.Empty).Length;

        Currently, if you try to compile "data.Length ?? 0" the compiler produces an error message, and that is good news because it gives us the opportunity to fix the "??" operator while still maintaining backward compatibility with the original behavior of the "??" operator.

        IMPORTANT: In other words, the proposed new (useful) behavior of the "??" operator can be implemented as an *extension* to the original rarely-used behavior, thereby maintaining compatibility.

        Thus my suggestion is to make the compiler accept and interpret the following as equivalent:

        int len = data.Length ?? alt;
        int len = object.ReferenceEquals(data,null) ? alt : data.Length;
        int len = (!object.ReferenceEquals(data,null)) ? data.Length : alt;

        Additional detail: The "??" operator should never invoke operator == or != overload functions, in my opinion. Whereas "a == null" does invoke overload, surprisingly. That is why I used object.ReferenceEquals() above.

        Thanks for considering it.

      • TimLovellSmithTimLovellSmith commented  ·   ·  Flag as inappropriate

        Couldn't it just be ?[] instead of ?.[] since after all, you normally never need a . for an array indexer.

      • BryanBryan commented  ·   ·  Flag as inappropriate

        I think this will be nice. I currently use an extension method with a Lambda function to do something similar, but this will be more efficient (no function call).
        Current Method:
        x.ValueOrDefault(x_ => x_.y);
        or with explicit DefalutValue
        x.ValueOrDefault(x_ => x_.y, 5);

      • AnonymousAnonymous commented  ·   ·  Flag as inappropriate

        I'd rather see a psuedo method like the following instead of more dense ? syntax.
        The fullnullcheck() would be expanded to the appropriate if (a != null) && (b != null) && ...
        at compile time.

        This has advantage of keeping the variable name in the if clause the same as in the then clause.

        if (fullnullcheck(a.b.c[2].d.e.f[6].g)
        {
        a.b.c[2].d.e.f[6].g.name = "abc";
        }

        I'd much rather have language feature that lets a property specify an on-change method
        private int identifier { get; set; OnChange { block of code} } that equates tot he following

        private int indenfier
        {
        get { return _identifierBackingVariable; }

        set
        {
        if (value == _identiferBAckingVarible)
        return;
        {on change block of code}
        _identifer_backingVarible = value;
        }
        }

      • Anonymous commented  ·   ·  Flag as inappropriate

        You know you can already kind of solve this issue with the following simple c# techniques

        - Extension method
        - Delegate
        - Generic
        - Lambda expresion

        Which gives us

        public static T eval<V, T>(this V v, Func<V, T> fn)
        {
        try { return fn(v); }
        catch { return default(T); }
        }

        Use it like that

        obj1.eval(x => x.obj2.obj3.obj4.obj5 etc...)

        It will either return the result of the expression or the default value for the type you are trying to get.

      • droiddroid commented  ·   ·  Flag as inappropriate

        Make it so that this:

        if [myclass.x.y.z] { }
        or this
        if (myclass.x.y.z)? { }
        or this
        if (?myclass.x.y.z) { }

        equals to null checking each of myclass, x, y, z and not throwing and not executing the { .. } if any were null or false.

        ... Just stirring the pot ...

      • Anonymous commented  ·   ·  Flag as inappropriate

        @aaronbauman you can always add a suggestion to the 'Languages - Visual Basic' section for that

      • Aaron BaumanAaron Bauman commented  ·   ·  Flag as inappropriate

        Representing a small portion of the VB world, please don't forget about us!

        I think it would be good if it checked DBNull as well as Nothing...

        If(IsDBNull(e) OrElse IsNothing(e), Nothing, e.x)

      • Michael JensenMichael Jensen commented  ·   ·  Flag as inappropriate

        will the indexing version of this (i.e. e?[0]) be able to check whether an index is out of bounds or not? (for common types like IList and Array, and maybe Dictionary at least?)

      • Anonymous commented  ·   ·  Flag as inappropriate

        @MadsTorgersen[MSFT] I think that one of the prime examples of where this could shine is in the case of event handlers:

        var myArgs = new Object();
        if (MyHandler != null)
        MyHandler(...);

        Will it be possible to write this? This would really make a lot of UI code cleaner. Especially because many event handlers are blind and don't care whether or not they have any subscribers

        var myArgs = new Object();
        MyHandler.?(myArgs);

        I wonder how long it will take Resharper to pick up on refactoring to this as well.......hmmm

      ← Previous 1 3 4 5 9 10

      Feedback and Knowledge Base