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,426 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 Asadzadeh shared this idea  ·   ·  Flag idea as inappropriate…  ·  Admin →

    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

    186 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...
      • gzak commented  ·   ·  Flag as inappropriate

        @ste, the first attempt with the bools still doesn't compile.

        You can't do "bool? b2 = !this.nullValue?.Hello();", you would have to leave out the ! and reverse the conditions in the rest of the code accordingly. But that's a small issue.

        You certainly can't do "this.nullValue?.Value = GetSomething();", since ?. constitutes an expression, and you can't assign to the result of an expression. For instance, you can't do this:

        x ?? y = "hello"; // even if x and y are both strings

        You can only do something like this:

        (x ?? y).Foo = "hello"; // x and y must be of the same type, thus both would have a Foo property

        In this case, that would mean:

        (this.nullValue?.Value).Something = GetSomething();

        Which implies nullValue and nullValue.Value have the same type

        All that said, I like your second less contrived example. It made me think :-)

        You're right, you wouldn't know in that case if Work returned null or if field was just null.

        My initial inclination is to say that ?. can only be used with properties and fields, not methods. Though if I were to allow methods, I'd say that methods must return value types, and using ?. automatically "lifts" the return type into a Nullable<T> type, so that there's no ambiguity on whether or not the method was actually called (it can't return null on its own, so if you get null it must mean that it wasn't called).

        It just occurred to me that this is still a bit contrived. When would you write code that "keeps going" in the face of repeated access failures? Surely this code is painful to write, and it would be far easier to just throw something early. Here's my rewrite without ?. to illustrate:

        object o = this.field != null ? this.field.Work() : null;

        if (o == null) { /* null check did indeed creep back in */ }

        object p = o != null ? o.MoreWork() : null;
        bool? success = p != null ? p.Etc() : null;
        return success ?? false;

        Not having a ?. didn't really change much, since writing it both with and without ?. is relatively similar so long as you make ample use of local variables. I think to really abuse ?. you'd need a very long one-liner with deeply nested accesses, but we've already said that this is a rare occurrence.

        The thing is, using ?. doesn't make it any easier to _write_ code which violates the law of demeter. It only makes it easier to _use_ code which has _already_ violated the law of demeter. Because if the code you're using didn't violate the law of demeter in the first place, you wouldn't need to deeply nest your property accesses.

        So the flaw is actually in the other code which violated the law of demeter, not in your code which tries to succinctly deal with it using ?.

        I suppose you can argue that by having ?. you are less inclined to fix the other code since you can now deal with it "easily", but a lot of times you simply don't own the other code at all.

        That, or the other code is a huge scary legacy mess (aka violates the law of demeter all over the place) which you'd rather not change because it's used in a million other places.

      • null commented  ·   ·  Flag as inappropriate

        That's my primary concern. I wouldn't miss-use it (perhaps..), but I know I will eventually have code written by someone who has.

        Sorry if the nay-sayers seem **** about "features" like this, but I've catches for "Exception" in every method, 'var' for every object, flow control using exceptions, and just general shoddiness.

        And with this "feature" the type-random-****-to-make-it-compile gang would have another weapon against us.

      • Anonymous commented  ·   ·  Flag as inappropriate

        yes exactly you would want it to fail
        if you know that it is possible for this to fail
        you want to rethink your pattern

        consider there was a situation were you had to deal with this like you were calling to someone else's code or something and you couldn't modify it
        it is a nightmare
        the solution would definatly NOT be
        to make dealing with that nightmare a constant occurance by introducing this bad coding motivator into the language itself so that others could easly cover up there terrible mistakes

      • ste commented  ·   ·  Flag as inappropriate

        Perhaps using bool was contrived...

        object o = this.field?.Work();

        if (o == null) {
        // null check creeped back - but did Work() actually return null, or was it because this.field is null?
        }

        or, carry on regardless? because I don't care if a value that I want to work on is null, and I don't want to know the point of failure...

        object p = o?.MoreWork();
        bool? success = p?.Etc();
        return success ?? false;

        That type of mentality is handy for client UI related scripts on untested browsers, where in most cases you just want the thing to run without complaining... but not on the server/desktop where you want it to fail, rather than continue executing under a false pretense with bad data.

      • ste commented  ·   ·  Flag as inappropriate

        @gzak: Thank you for answering me with something constructive, it's improved my understanding.

        However,
        if (this.nullValue != null) { b = this.nullValue.Work(); }
        becomes:
        b = this.nullValue?.Work();
        more readable? debatable. Concise? definitely.

        However, when you actually use 'b':
        // current:
        if (b)
        {
        // yes
        }
        else
        {
        // no
        }

        // proposal:
        if (b == true)
        {
        // yes
        }
        else if (b == false)
        {
        // no
        }
        else
        {
        // b is null, so the original null check has really been moved to here
        }

        also, notice the extra "== true/false" checks?

        I will accept your challenge and rewrite, but it looks like null checks still can't be avoided:

        if (this.nullValue?.Hello() == true) { }
        bool? b2 = !this.nullValue?.Hello();
        if (b2 == true) { } else if (b2 == false) { }

        b = c = this.nullValue?.GetBool();
        // b and c could now be true, false, or null

        this.nullValue?.Value = GetSomething(); // is GetSomething() even called?

        b = this.nullValue?.Value = GetSomething(); // what's b now?
        // is b the return of GetSomething()? or null?

        bool x? = this.nullValue?.Value;
        if (x != null) { DoWork((bool)x); }

      • Anonymous commented  ·   ·  Flag as inappropriate

        id like to add you can override types to make them <nullable> which is what should have been done in all these examples
        maybe no one made a pattern for that
        but they should have

        then such calls would simply be
        if(A.B.C.D == null){ /* ?? now how well did you design this *****/ }

      • Anonymous commented  ·   ·  Flag as inappropriate

        so for the typo but all that code is even more unreadable then my punctuation
        really that is anti pattern if i ever saw it
        the times were you need to write that kinda null check i can only really see as were your doing some kinda call to poorly poorly designed library
        in that case you are better off if you dont add something to a language that encourages others to write even more ****

      • Anonymous commented  ·   ·  Flag as inappropriate

        im sorry i dont use much linq so maybe i need some enlightenment or maybe im not *** backwards

        but every single example of why this is needed looks something like this
        so let me put a different spin on this for people who dont get it

        I want to access a property A.B.C.D exactly once, where any of the members might be null. Which is nicer, this:

        so here is a quote
        "
        Object myVar;
        if(A != null)
        {
        if(A.B != null)
        {
        if(A.B.C != null)
        {
        myVar = A.B.C.D;
        }
        }
        }

        or this:

        var myVar = A.?B.?C.?D;

        And note, method 1 didn't even use temporary variables, which would make the code even more verbose!
        "

        and here is the problem so now we have guys who write code that calls thru 4 f#$# class's and they dont even know if what they are calling is null or not
        does this look like the kind of code base YOU want to inhearit ? ?? ???? ????????????????????????????????????????????

      • gzak commented  ·   ·  Flag as inappropriate

        @John Saunders, in the same way that we've lived without async/await for an entire decade (and suffered greatly for it)?

        Also, nobody said that this will be "the new way" to handle null checking. In the same way that you don't wrap every single line of code with try/catch or null-checks today, you similarly wouldn't suddenly change every . to a ?.

        I think @Jimmy unwittingly demonstrated the best and by far most common use case for this operator. All those other examples with deeply nested properties are very contrived, and are seldom encountered in real code.

      • Jamshid Asadzadeh commented  ·   ·  Flag as inappropriate

        Guys! You don't "have to" use the provided example in the idea's description. As I stated in the description too, it is just an EXAMPLE. In Mose cases you would use it for just one level (like myObject?.item). Please....You can abuse any given operator or statement if you want.

      • gzak commented  ·   ·  Flag as inappropriate

        @ste

        The very first line of your counterexample has a bug.

        If 'b' is of type bool (which is likely the intent), the statement on the right returns Nullable<bool> so it wouldn't compile. The rest of the counterexample falls apart similarly.

        Actually, with my comment in mind, try rewriting your example in such a way that it would compile, as an exercise, and see if it's not cleaner.

        @Jimmy, what if myObject itself is null? That line will still crash when it's pretty clear from the intent that you don't care about any nulls on the left of the ?? because you have a catch-all default ready and waiting on the right.

        How would you make that line not crash today? Well, the most concise I could come up with is this:

        string vsSearch = "Guess ...";
        if (myObject != null && myObject.Item != null) vsSearch = myObject.Item;

        Notice I couldn't even use the ?? operator, because doing so would force me to write the "Guess ..." string twice, or it wouldn't be as concise (try it). Essentially, the lack of a ?. operator cripples the usefulness of the ?? operator in a lot of cases (case in point). Which isn't surprising, since they are fundamentally two sides of a single coin (from a monadic perspective). It would be like having "catch" without "throw", or something similar. You need both sides of the coin for it to be fully useful.

      • Jimmy commented  ·   ·  Flag as inappropriate

        Try

        string vsSearch = myObject.Item ?? "Guess I'm null so return this statement...";

      • Jamshid Asadzadeh commented  ·   ·  Flag as inappropriate

        I don't know why so many .net people actually resist in learning from other good technologies out there! Get your heads out of the snow a little bit and see how others are running you over! You don't need to be a red neck about every new idea that gets you out of your comfort zone. Not every language feature needs to be compatible with "your" style of coding. It's these tiny flexible features that make a good language great.

      • noname commented  ·   ·  Flag as inappropriate

        Instead ?. I used dynamic object and ?? operator.
        Like:
        ((myObj ?? dynObj).Items ?? dynObj)[0]

        This work only if returning types are object or we want to execute some void returning method.

      • ste commented  ·   ·  Flag as inappropriate

        b = this.nullValue?.Work(); // what is b set to? false? stays the same?
        // why false? or stay the same?
        bool failed = this.nullValue?.Work();
        if (!failed) { EverythingIsOK(); }

        if (this.nullValue?.Hello()) { /* is this block executed? */ }
        if (!this.nullValue?.Hello()) { /* is this? */ } else { /* or this? */ }

        b = c = this.nullValue?.GetBool(); // what about this?
        this.nullValue?.Value = GetSomething(); // is GetSomething() even called?
        b = this.nullValue?.Value = GetSomething(); // what's b now?

        DoWork(this.nullValue?.Value); // what's passed to DoWork()? null? So should you catch ArgumentNullException? no, it's better check first..
        if (this.nullValue?.Value == null) { DoWork(this.nullValue?.Value); } // oh, that naughty null check has sneeked back in!

        and I've only scratched the surface...

      • ste commented  ·   ·  Flag as inappropriate

        Code smell alert!!
        It would be a nightmare to maintain code that is littered with these types of null checks, hiding null references and continuing as though nothing is wrong!

        If you don't want to execute something upon a certain condition.. then use an "if" statement!!

        By the way, it's implemented in CoffeeScript not only to check for null, but to also determine if an object actually contains the specified member (at runtime), which very common when dealing with the browser DOM, and most times you want your script to "just work".

        Sorry if I'm appearing to be elitist, but the fact that there are over 2000 votes shows the sorry state that the developer community currently is, and no wonder MS are continually dumbing down Visual Studio.

      • John Saunders commented  ·   ·  Flag as inappropriate

        @Olmo: if this feature is "a must", then please explain how we managed to live without it for the entire decade that C# has existed!

        I'll say again, that the need for this much null checking is a sign of a badly-designed system. Quite likely, there is code that should have thrown an exception instead of returning null.

      Feedback and Knowledge Base