C#6: Null-conditional operators

With the release of Visual Studio 2015 in July came C# 6. Each iteration of C# has tended to have a theme and if there were a theme for this one, it would be developer productivity; all the new features in C# 6 appear to be either improvements to existing features, or syntactical shortcuts to simplify common operations. One of those syntactical shortcuts is the `?.` operator1, which is accompanied by the similar `?[]` operator2.

These new operators are collectively known as null-conditional operators. Most, if not all C# developers have used the null-coalescing operator, `??` and found it to be brilliant…until the next step was to call a method or property on the result. Though `(something ?? somethingelse).Property` seems like it might be a good idea, there is rarely a suitable `somethingelse` that doesn't just feel like hack, so invariably, we resort to an `if` or the conditional operator, `?:`3.

var x = new MyClass();

ReturnTypeOfDoSomethingCool y = null;
if (x != null)
{
    y = x.DoSomethingCool();
}

// or, perhaps,

var y = x == null ?4;

In C# 6, the `?.` and `?[]` operators step up to help. These new null-conditional operators check the value on the left of the operator and, if it is null, return null, short-circuiting the remainder of the expression; if the value on the left of the operator is non-null, the expression continues according to precedence rules.

Using these operators, we can express our earlier code much more succinctly and without resorting to convoluted, hacky `??` chains.

var x = new MyClass();
var y = x?.DoSomethingCool();

// and, with an indexer,

var a = new List<int>();
Console.WriteLine( a?[0] ?? "nothing" );

There isn't much else to write about these simple operators except to draw attention to how `?.` works with `Nullable<T>` types such as `int?`5. Consider the `??` operator. When the `??` operator is applied to a nullable type like `int?`, it either returns the value wrapped in that `int?` or the value evaluated from the right of the operator. That is to say that instead of needing to reference the `Value` property of the nullable directly, the operator does that for you. The following assignment works because `x.Value` is returned from the `??` operator, not `x`.

int? x = 10;
int y = x ?? 0;

The `?.` operator works the same way, which means the following does not make sense and won't compile; `Value` is not a property of `int`:

int? x = 10;
int y = x?.Value;

Whereas this will work just fine:

int? x = 10;
string y = x?.ToString();

In Conclusion…

The null-conditional operators, `?.` and `?[]` provide some shortcuts that will no doubt lead to clearer code, and I welcome their addition to the C# language. I hope that you do to.

 

  1. aka, the one-eyed Elvis operator []
  2. the robot Elvis, or Howard The Duck []
  3. The two-eyed Elvis []
  4. ReturnTypeOfDoSomethingCool)null) : x.DoSomethingCool();

    Or, if using an indexer:

    var x = new List<int>();
    if (x != null)
    {
       Console.WriteLine(x[0]);
    }
    
    Console.WriteLine(x == null ? "nothing" : x[0].ToString( []
  5. also expressible as `Nullable<int>` []

LINQ: Clarity, complexity, and understanding

This is part of a short series on the basics of LINQ:

At CareEvolution, we tend to develop using JavaScript on the front end, and C# on the back end (with some Python, PowerShell, CoffeeScript, R, SQL, and other languages thrown in when appropriate or technical debt dictates). We have hackathons every eight weeks where we get to be creative without the constraints of day-to-day work. We have a brown bag lunch talk every Wednesday. We work hard at embracing change, exploring new ways of doing things, and sharing what we have learned with each other. Quite often, leading figures in a particular technology emerge within our organisation: Brian knows JavaScript, Chris knows CSS, Brad knows SQL. While I doubt I know even half of the things about LINQ and its various implementations for database, Web API, or file interaction, I know enough to make it useful in my day to day work and I seem to be the one that employs it most in their code. I know LINQ.

I am certain this is going to sound familiar to many, but while my colleagues and I embrace all things as a collective, quite often a specific technology or its use will be avoided, derided, and hated by some. Whether driven by ignorance, a particular terrible experience, or prejudice1, these deep-seated feelings can create conflict and occasionally hinder progress. For me, my use of LINQ has been a cause for contention during code reviews. I have faced comments like "LINQ is too hard to understand", "loops are clearer", "it's too easy to get burned using LINQ", and "I don't know how to use it so I'd prefer not to see it". And that's all true; LINQ can be confusing, it can be complicated, it can be a debugging nightmare. LINQ can suck. Whether you use the C# language keywords or the dot notation (a debate almost as passionate as tabs versus spaces), LINQ can tie you up in knots and leave you wondering what you did to deserve this fresh hell. Yet any technology could be described the same way when one doesn't know anything about it or when early mistakes have left a bitter aftertaste.

Tabs vs Spaces

In response to these dissenting voices, I usually indicate the years of academic learning and professional experience it takes us to learn how to code at all. None of it is particularly easy and straightforward without some education. Don't believe me? Go stick your mum or dad in front of Visual Studio and, assuming they have never learned anything about C# or programming, see how far they get on writing Hello World without your help. Without educational instruction, we would not know any of it and LINQ is no different. When review comments inevitably request that I change my code to use less LINQ, none at all, or more understood language features like `foreach` and `while` loops, it frustrates me. It frustrates me because I usually feel that LINQ was the right choice for the job. I feel like I am being told, "use something I already know so I don't have to learn."

Of course, this interpretation is hyperbole. In actuality, when presented with opposing views to our own, it is easy to commit the black or white fallacy and assume one must be right and the other wrong, when really we should accept that we both may have a point (or neither) and learn more about the opposing view. Since I find, when used appropriately, LINQ can provide the best, most sublime, most elegant solution to problems that require the manipulation of collections in C#, I desperately want others to see that. It is as much on me as anyone else to try and correct for the disparity between what I see and what others see when I write LINQ. So, with my next post we will begin a journey into the basics of LINQ, when to use it2, when to use dot notation over language keywords (or vice versa), and how to avoid some of the more common traps. We will begin with the cause of many confusing experiences; deferred execution.

  1. we all know someone in the "That's new, I hate it" crowd []
  2. even I recognize LINQ is not a golden hammer; it's more of a chainsaw that kicks a little []