C# 6.0

My 5 Favorite C# 6.0 Features

With C# 6 nearly upon us I thought it would be a good time to revisit some of the upcoming language features. A lot has changed since I last wrote about the proposed new features so let’s take a look at what’s ahead.

I think it’s fair to say that have mixed feelings about this release as far as language features go especially since many of my favorite proposed features were cut. I was particularly sad to see primary constructors go because of how much waste is involved with explicitly creating a constructor, especially when compared to the same activity in F#. Similarly, declaration expressions would have nearly fixed another of my least favorite things in C# – declaring variables to hold out parameters outside of the block where they’re used. Being able to declare those variables inline would have been a welcome improvement. That said, I think there are some nice additions to the language. Here’s a rundown of my top five favorite C# 6.0 language features in no particular order.

Auto-Property Initialization Enhancements

The auto-property initialization enhancements give us a convenient way to define an auto-property and set its initial value without necessarily having to also wire up a constructor. Here’s a trivial example where the Radius property on a Circle class is initialized to zero:

public class Circle
{
    public int Radius { get; set; } = 0;
}

The same syntax is available for auto-properties with private setters like this:

public class Circle
{
    public int Radius { get; private set; } = 0;
}

So we saved a few keystrokes by not needing a constructor. Big deal, right? If this were the end of the story, this feature definitely wouldn’t have made this list but there’s one more variant that I’m really excited about: getter-only auto-properties. Here’s the same class revised to use a getter-only auto-property:

public class Circle
{
    public int Radius { get; } = 0;
}

Syntactically these don’t differ much but behind the scenes is a different story. What getter-only auto-properties give us is true immutability and that’s why I’m so excited about this feature. When using the private setter version, the class is immutable from the outside but anything inside the class can still change those values. For instance,

in the private setter version it would be perfectly valid to have a Resize method that could change Radius. Getter-only auto-properties are different in that the compiler generates a readonly backing field making it impossible to change the value from anywhere outside of the constructor. This is important because now, when combined with a constructor we have a fairly convenient mechanism for creating immutable objects.

public class Circle
{
    public int Radius { get; }

    public Circle(int radius)
    {
        Radius = radius;
    }
}

Now this isn’t quite as terse as F#’s record types but by guiding developers toward building immutable types, it’s definitely a step in the right direction.

Using Static

Using static allows us to access static methods as though they were globally available without specifying the class name. This is largely a convenience feature but when applied sparingly it can not only simplify code but also make the intent more apparent. For instance, a method to find the distance between two points might look like this:

public double FindDistance(Point other)
{
    return Math.Sqrt(Math.Pow(this.X - other.X, 2) + Math.Pow(this.Y - other.Y, 2));
}

Although this is a simple example, the intent of the code is easily lost because the formula is broken up by references to the Math object. To solve this, C# 6 lets us make static members of a type available without the type prefix via new using static directives. Here’s how we’d include System.Math’s static methods:

using static System.Math;

Now that System.Math is imported and its methods are available in the source file we can then remove the references to Math from the remaining code which leaves us with this:

public double FindDistance(Point other)
{
    return Sqrt(Pow(this.X - other.X, 2) + Pow(this.Y - other.Y, 2));
}

Without the references to Math, the formula becomes a bit clearer.

A side-benefit of using static is that we’re not limited to static methods – if it’s static, we can use it. For example, you could include a using static directive for System.Drawing.Color to avoid having to prefix every reference to a color with the type name.

Expression-Bodied Members

Expression-bodied members easily count as one of my favorite C# 6 feature because they elevate the importance of expressions within the traditionally statement-based language by allowing us to supply method, operator, and read-only property bodies with a lambda expression-like syntax. For instance, we could define a ToString method on our Circle class from earlier as follows:

public override string ToString() => $"Radius: {Radius}";

Note that the above snippet uses another new feature: string interpolation. We’ll cover that shortly.

At first glance it may appear that this feature is somewhat limited because C#’s statement-based nature automatically reduces the list of things that can serve as the member body. For this reason I was sad to see the semicolon operator removed from C# 6 because it would have added quite a bit of power to expression-bodied members. Unfortunately the semicolon operator really just traded one syntax for an only slightly improved syntax.

If expression-bodied members are so limited why are they on this list? Keep in mind that any expression can be used as the body. As such we can easily extend the power of expression-bodied members by programming in a more functional style.

Consider a method to read a text file from a stream. By using the Disposable.Using method defined in the linked functional article, we can reduce the body to a single expression as follows:

public static string ReadFile(string fileName) =>
    Disposable.Using(
        () => System.IO.File.OpenText(fileName),
        r => r.ReadToEnd());

Without taking advantage of C#’s functional features, such an expression wouldn’t be possible but in doing so we greatly extend the capabilities of this feature. Essentially, whenever the property or method body would be reduced to a return statement by using the described approach, you can use an expression-bodied member instead.

String Interpolation

Ahhh, string interpolation. When I first learned that this feature would be included in C# 6 I had flashbacks to the early days of my career when I was maintaining some Perl CGI scripts. String interpolation was one of those things that I always wondered why it wasn’t part of C# but String.Format, while moderately annoying, always worked well enough that it wasn’t particularly a problem. Thanks to a new string literal syntax, C# 6 will let us define format strings without explicitly calling String.Format by allowing us to include identifiers and expressions within holes in the literal. The compiler will detect the string and handle the formatting as appropriate by filling the holes with the appropriate value.

To define an interpolated string, simply prefix a string literal with a dollar sign ($). Anything that should be injected into the string is simply included inline in the literal and enclosed in curly braces just as with String.Format. We already saw an example of string interpolation but let’s take another look at the example:

public override string ToString() => $"Radius: {Radius}";

Here, we’re simply returning a string that describes the circle in terms of its radius using string interpolation. String.Format is conspicuously missing and rather than a numeric placeholder we directly reference the Radius property within the string literal. Just as with String.Format, we can also include format and alignment specifiers within the holes. Here’s the ToString method showing the radius to two decimal places:

public override string ToString() => $"Radius: {Radius:0.00}";

One of the things that makes string interpolation so exciting is that we’re not limited to simple identifiers; we can also use expressions. For instance, if our ToString method was supposed to show the circle’s area instead, we could include the expression directly as follows or even invoke a method:

public override string ToString() => $"Area: {PI * Pow(Radius, 2)}";

The ability to include expressions within interpolated strings is really powerful but, as Bill Wagner recently pointed out, the compiler can get tripped up on some things. Bill notes the conditional operator as one such scenario. When the conditional operator is included in a hole the colon character confuses the compiler because the colon is used to signify both the else part of the conditional operator and to delimit the format specifier in the hole. If this is something you run into, simply wrap the conditional in parenthesis to inform the compiler that everything within the parens is the expression.

Null-Conditional Operators

Finally we come to the fifth and final new feature in this list; a feature I consider to be a necessary evil: the null-conditional operators. The null conditional operators are a convenient way to reduce the number of null checks we have to perform when drilling down into an object’s properties or elements by short-circuiting when a null value is encountered. To see why this is useful consider the following scenario.

Imagine you have an array of objects that represent some type of batch job. These objects each have nullable DateTime properties representing when the job started and completed. If we wanted to determine when a particular job completed we’d not only need to make sure that the item at the selected index isn’t null but also that the completed property isn’t null, either. Such code might look like this:

DateTime? completed = null;

if(jobs[0] != null)
{
    if(jobs[0].Completed != null)
    {
        completed = jobs[0].Completed;
    }
}

WriteLine($"Completed: {completed ?? DateTime.MaxValue}");

That’s quite a bit of code for something rather trivial and it distracts from the task of getting the completed time for a job. That’s where the null-conditional operators come in. By using the null-conditional operators, we can reduce the above code to a single line:

WriteLine($"Completed: {jobs?[0]?.Completed ?? DateTime.MaxValue}");

This snippet demonstrates both of the null-conditional operators. First is the ? ahead of the indexer. This returns if the element at that index is null. Next is the ?. operator which returns if the member on the right is null. Finally, we see how the null-conditional operators can be used in conjunction with the null-coalescing operator to combine the giant if block into a single expression.

So why do I consider this feature a necessary evil? The reason is that I consider null to be evil, null references have been called The Billion Dollar Mistake, and Bob Martin discussed the evils of null in Clean Code. In general, nulls should be avoided and dealing with them is a costly nuisance. I think that these null-conditional operators, which are also sometimes collectively referred to as the null-propagation operators, will do just what that name implies – rather than promoting good coding practices where null is avoided, including the null-conditional operators will encourage developers to sloppily pass or return null rather than considering whether null is actually a legitimate value with the context (hint: it’s not). Unfortunately, null is an ingrained part of C# so we have to deal with it. As such, the null-conditional operators seem like a fairly elegant way to reduce null’s impact while still allowing it exist.

Wrap-up

There you have it, my five favorite C# 6 language features: auto-property initialization enhancements, using static, expression-bodied members, string interpolation, and the null-conditional operators. I recognize that some popular features such as the nameof operator and exception filters didn’t make the cut. While I definitely see their appeal I think they’re limited to a few isolated use cases rather than serving as more general purpose features and as such I don’t anticipate using them all that often. Did I miss anything? Let me know in the comments.

Advertisements

C# 6.0 – String Interpolation

[7/30/2015] This article was written against a pre-release version of C# 6.0. Be sure to check out the list of my five favorite C# 6.0 features for content written against the release!

I really debated about whether I should write about C#’s upcoming string interpolation feature yet. On one hand it’s an interesting feature that I’m looking forward to. On the other hand, it has already been announced that the feature is going to change from its implementation in the current preview. With that in mind I decided that it’s interesting enough to go ahead and write about it using the current syntax but highlight how it will change, much like how it has been done in the feature description document.

When I first heard that string interpolation was coming to C# I immediately experienced flashbacks to the very early days of my career when I was working with some Perl scripts. I really hated working with the language but something that always stuck with me and I missed when jumping to other languages was its string interpolation feature.

At a glance, Perl’s string interpolation feature let us embed variable names inside string literals and the compiler would handle the details of replacing the variable name with the value. My Perl is rusty to say the least but a simple example would essentially look like this:

my $name = "Dave";
print "My name is $name";

Upon execution, the script would write out the following text:

My name is Dave

Side note: I think this is the first time Perl has appeared on this blog. Hopefully it’ll be the last!

Perl’s implementation is more advanced than I’ve shown in this example but it clearly shows the usefulness of the feature. When .NET finally came along and I learned about String.Format I had hopes that it could evolve into something like the Perl feature described above. String.Format is certainly a useful method but it can quickly become a maintenance headache.

Traditional format strings have a number of problems each stemming from the index-based hole approach. First, each value must be supplied in the order that corresponds to the index which isn’t necessarily the order that the values appear in the string. Next, as the number of holes increases, it can be difficult to discern what each hole represents. This isn’t normally a problem for strings with only a few holes but consider the nightmare of keeping indices straight on a format string with more than 50 holes like I once encountered. Finally, String.Format validates only that enough values were supplied to fill each of the holes but if values were provided than there are holes there’s not even a compiler warning. Combine this with one of those 57-hole strings and good luck finding which indices are off or which values should be removed.

C#’s string interpolation aims to fix each of the aforementioned problems. The current implementation uses a slightly clunky version of the traditional format string syntax in that each hole must be prefixed with a backslash. Here’s how the previous example would be written in C# 6.0 using the syntax that’s in the current preview:

var name = "Dave";
WriteLine("My name is \{name}");

Just as in the Perl example, the compiler will resolve the name and fill the hole with the appropriate value. What’s more is that the compiler also verifies that each name exists in the current context and flags anything it can’t resolve as an error.

Per the upcoming features document, this syntax will be changed to something a bit friendlier. Rather than prefixing each hole with a backslash, the string will be identified as an interpolated string by prefixing it with a dollar sign like this:

var name = "Dave";
WriteLine($"My name is {name}");

In this trivial example the net effect on the code is moving and replacing a single character but it’s easy to imagine more complex interpolated strings becoming significantly shorter. (There will also be a FormattedString class added to the System.Runtime.CompilerServices namespace to facilitate custom formatting via the IFormattable interface but I won’t cover that in this article).

That interpolated strings (in either form) closely resemble traditional format strings is not entirely coincidental because ultimately, each interpolated string is syntactic sugar for invoking String.Format. Essentially, the compiler replaces each of the named holes with indexed holes and constructs the value array from the provided names. The benefit of this is that anything you can do with traditional format strings such as including alignment and format specifiers also is also possible with interpolated strings. For instance, we could easily represent a date in ISO 8601 format as follows:

"Current Date and Time (UTC): \{DateTime.UtcNow:o}"

So that’s C#’s string interpolation feature in a nutshell and I’m pretty excited about the direction it’s going because it’ll gradually clean up a lot of code. Since the feature is still under development there’s an active discussion in progress over on the Roslyn site. If you’re interested in seeing some of the thought process behind where this feature is going I encourage you to check it out.

C# 6.0 – nameof Expressions

[7/30/2015] This article was written against a pre-release version of C# 6.0. Be sure to check out the list of my five favorite C# 6.0 features for content written against the release!

I’ve lost track of the number of times I’ve needed to pass along the name of something be it a property, method, or type. Historically we’ve relied on hard-coded strings to convey this information but as we’re all too well aware, relying on strings in such a manner is just asking for future problems. For a prime example, we need look no further than our old friend INotifyPropertyChanged.

Consider the following Circle class which typifies the basic INotifyPropertyChanged implementation pattern:

public class Circle
  : INotifyPropertyChanged
{
  public event PropertyChangedEventHandler PropertyChanged;

  private double _radius;
  public double Radius
  {
    get { return _radius; }
    set
    {
      _radius = value;
      RaisePropertyChanged("Radius");
    }
  }

  private void RaisePropertyChanged(string propertyName)
  {
    if (PropertyChanged == null) return;

    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
  }
}

Although this class is pretty boilerplate, it highlights the problem well. First, we’ve violated the DRY principle by encoding a member name in a string. Next, we’ve introduced fragility by relying on the string always reflecting the property name exactly; should the property name ever change we need to remember to change the string as well lest we waste some cycles tracking down why an event handler isn’t picking up the property change. What’s worse is that by encoding the name within a string, we get no compile-time support alerting us to the discrepancy.

The story around INotifyPropertyChanged and other similar scenarios has improved over the years as people have come up with some creative solutions. For instance, I’m particularly fond of the expression tree approach because despite its added complexity, it adds the compile-time support lacking in the string-based approach and ties in nicely to Visual Studio’s built-in refactoring capabilities.

.NET 4.5 improved the story a bit more by introducing a few attributes we could apply to optional parameters to get information about the method caller with CallerMemberNameAttribute being the most notable for this discussion. By decorating a parameter with CallerMemberNameAttribute as shown in the revised RaisePropertyChanged method that follows we’re instructing the compiler to inject the name of the member that invoked the method.

private void RaisePropertyChanged([CallerMemberName] string propertyName = "")
{
  if (PropertyChanged == null) return;

  PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}

With this revised version, we could simply invoke the method without passing the name and the compiler would resolve the name for us. The problem with this approach is that there’s nothing in IntelliSense to inform us that the parameter is decorated with the attribute and there’s nothing stopping us from providing a value. In fact, the compiler won’t even warn that a name won’t be resolved if we do provide a value. Furthermore, while CallerMemberNameAttribute works nicely for this example, it’s only useful when we need the caller name so it won’t help us if we need the name of anything else such as a parameter name. That’s where the new nameof operator comes in.

C# 6.0’s nameof operator is used to resolve the name of an item at compile-time, essentially inserting the string into the compiled code. What’s really great about it is that it’s simple to use and works on any symbol.

In keeping with the INotifyPropertyChanged example, in C# 6.0 we can add compile-time safety to the original example code simply by replacing:

RaisePropertyChanged("Radius");

with:

RaisePropertyChanged(nameof(Radius));

There are plenty of other places I can see the nameof operator coming in handy. For instance, I often like to use a Guard class to perform a variety of pre-condition checks against method parameter values. Such a class typically looks a bit like this:

public sealed class Guard
{
  private static Lazy<Guard> _against = new Lazy<Guard>();

  public static Guard Against { get { return _against.Value; } }

  public void Null(string arg, object value)
  {
    if (value == null) throw new ArgumentNullException(arg);
  }

  // additional guard methods here
}

I generally create the Guard class as a sealed singleton class rather than as a static class to not only create a more English-like API, but also to allow extension methods in certain scenarios. I also like defining the Guard class methods as a fluent interface but omitted that for brevity.

Given that the Guard class operates off of arguments rather than callers, adding parameters decorated with CallerMemberNameAttribute clearly won’t work in this scenario. Instead we can simply update calls to the various methods to use the nameof operator instead of a hard-coded string and our code will immediately be less fragile.

C# 6.0 – Expression-bodied Members

[7/30/2015] This article was written against a pre-release version of C# 6.0. Be sure to check out the list of my five favorite C# 6.0 features for content written against the release!

Expression-bodied members are another set of features that simply add some syntactic convenience to C# to continue streamlining type definitions. C# type definitions have always been a bit tedious, requiring us to provide curly braces and explicit returns even when the function consists of only a single line. Lambda expressions have spoiled us by abstracting away most of the syntax that’s typically associated with functions and finally making delegation feel like a natural part of the language. Expression-bodied members extend the convenience of lambda expressions to type members… to an extent.

According to the Visual Studio “14” CTP3 notes, expression-bodied members can be used for methods, user-defined operators, type conversions, and read-only properties including indexers (although expression-bodied indexers don’t work properly in the CTP).

To demonstrate the feature, I’ll define a custom RgbColor class and using expression-bodied members for both a hexadecimal formatting method and a custom negation operator.

public class RgbColor(int r, int g, int b)
{
  public int Red { get; } = r;
  public int Green { get; } = g;
  public int Blue { get; } = b;

  public string ToHex() =>
    string.Format("#{0:X2}{1:X2}{2:X2}", Red, Green, Blue);

  public static RgbColor operator - (RgbColor color) =>
    new RgbColor(
      color.Red ^ 0xFF,
      color.Green ^ 0xFF,
      color.Blue ^ 0xFF
    );
}

As convenient as expression-bodied members appear on the surface, they seem rather limited in their utility since their very nature requires expressions. This fact is compounded by the fact that C# isn’t an expression-based language; if it were (as F# is) we could get away with defining more complex bodies including some intermediate values such as a regular expression match result. As it stands today it’s not possible to do this without first defining that logic in a separate method that can be invoked from the expression-bodied member but that seems to defeat the purpose. Perhaps this would be a good use for the semicolon operator since we can’t even include that logic within curly braces as we could with a lambda expression.

C# 6.0 – Params IEnumerable

[7/30/2015] This article was written against a pre-release version of C# 6.0 and didn’t make it into the final product. Be sure to check out the list of my five favorite C# 6.0 features for content written against the release!

One of the items currently listed as “planned” on the Language Feature Implementation Status page is params IEnumerable. This is one of those features that I’ve thought could be nice but I’ve never really felt strongly about it one way or another mainly because I avoid params arrays whenever possible. I think the only time I actually use them consistently is with String.Format and its cousin methods. Before diving into the new feature, let’s revisit params arrays so I can better explain why I avoid them and why I’m so apathetic about this proposed feature.

The idea behind params arrays is that they let us pass an arbitrary number of arguments to a method by defining said method such that its final parameter is an array modified by the params keyword. When we invoke the function, the compiler implicitly creates an array from the final parameters and is then passed to the method. In the method body, we typically access those values through the array. The following function shows this in action:

string MyStringFormat(string format, params string[] tokens)
{
  return
    Regex.Replace(
      format,
      @"\{(?<index>\d+)\}",
      m => tokens[Int32.Parse(m.Groups["index"].Value)].ToString());
}

We could then invoke this function as follows:

var format = "[{0}] Hello, {1}.";
var time = DateTime.Now.ToShortTimeString();
var name = "Guest";

var str = MyStringFormat(format, time, name);
// [10:35 PM] Hello, Guest.

Back in the early days of the .NET Framework, before we had collection initializers, the above was far more convenient than using an array directly. Now that collection initializers let us define arrays inline, we can simply write this:

var str = MyStringFormat(format, new [] { time, name });
// [10:35 PM] Hello, Guest.

Arguably, the former is a bit cleaner than the later because of the inline array definition but I have two problems with it. First, it masks the fact that an array is involved, and second, params arrays can really wreak havoc on overload resolution if you’re not careful with them. Assume we need to overload the MyStringFormat method to accept another string that will control some formatting options. We can’t tack the string on to the end of the parameter list because params arrays must appear last so we insert it at the front like this:

Note: I’m using string constants here for illustration purposes. A less contrived example would likely use an enum, thus avoiding the problem.

static class StringTransform
{
  public const string Uppercase = "Uppercase";
  public const string Lowercase = "Lowercase";
}

string MyStringFormat(string transformation, string format, params string[] tokens)
{
  var str = MyStringFormat(format, tokens);
  
  switch (transformation)
  {
    case StringTransform.Uppercase: return str.ToUpper();
    case StringTransform.Lowercase: return str.ToLower();
  }      

  return str;
}

Now we can invoke this new overload as follows:

var str = MyStringFormat(StringTransform.Uppercase, format, time, name);

…and the result would be as we would expect:

[12:30 AM] HELLO, GUEST.

But now that we have two overloads (each accepting an indeterminate number of strings) the compiler cannot always properly determine which overload to invoke. Let’s see what happens when we supply only three arguments as we did in the first example.

var str = MyStringFormat(format, time, name);

Now the result is:

12:30 AM

What happened? The compiler recognized that there are multiple candidate overloads so it took a greedy approach, selecting the overload with the most explicit parameters. As a result, each of the arguments were essentially shifted to the left of what we expected. In other words, what should have been the format parameter was treated as the transformation parameter, the first of the token values was treated as the format parameter, and so on. To force the compiler to use the correct overload, we can just be explicit with the array as we saw in the second example above:

var str = MyStringFormat(format, new [] { time, name });

So what does all of this have to do with params IEnumerable? Params IEnumerable is an extension of the core idea; rather than treating the last arguments as an array within the method, we’d treat them as a sequence. That is, in our MyStringFormat method, we’d define the final parameter as params IEnumerable<string> tokens rather than params string[] tokens.

This change makes sense from a language perspective especially since params arrays were implemented long before IEnumerable<T> was a central concept within the framework. But, as the May 21st design notes state, when the method is used as a params method (rather than by passing an explicit sequence), the compiler will still generate an array at the call site. For all other cases, passing a sequence will behave no differently than if the parameter had been defined without the params modifier.

Given that:

  • it’s so easy to define sequences inline
  • using params arrays can easily confuse the overload resolver
  • params IEnumerable will only hide the sequence’s details from the method implementation but otherwise have no effect on the code

…I don’t see myself ever using this feature. I’ll likely continue designing methods to accept IEnumerable<T> without including the params modifier to avoid the problems and be more specific about what the method is expected to do.

C# 6.0 – Semicolon Operator

I first read about the proposed semicolon operator a few weeks ago and, to be honest, I’m a bit surprised by the desire for it in C# if for no reason other than that C# isn’t an expression-based language. To me, this feature feels like another attempt to shoehorn functional approaches into an object-oriented language. If I understand the feature correctly, the idea is to allow variables to be defined within and scoped to an expression. The following snippet adapted from the language feature implementation status page shows the operator in action:

var result = (var x = Foo(); Write(x); x * x);

In this code, everything within the parentheses constitutes a single expression. The expression invokes Foo, assigns the result to x, passes x to the Write function, then returns the square of x, and ultimately assigns the square to result. Because x is scoped to the expression, it is not visible outside of the parenthesis. I think this seems a bit awkward in C# and what’s more, I don’t know what value it adds that functions don’t already give us. I haven’t really decided whether the above example is more readable or maintainable than if we’d defined a function called WriteAndSquare.

Interestingly, this capability already exists in F# (albeit in a slightly more verbose form) which isn’t really all that surprising since F# is an expression-based language.

let result =
  let x = Foo()
  printfn "%i" x
  x * x

Even in F# though, I think I’d still prefer factoring out the expression into a function.

C# 6.0 – Null Propagation Operator

[7/30/2015] This article was written against a pre-release version of C# 6.0 but is still relevant. Be sure to check out the list of my five favorite C# 6.0 features for content written against the release!

One of the most common complaints about C# (especially among the F# crowd) is the amount of code required to properly deal with null values. Consider the following type definitions and invocation chain:

Type Definitions

class PriceBreak(int min, int max, double price)
{
  public int MinQuantity { get; } = min;
  public int MaxQuantity { get; } = max;
  public double Price { get; } = price;
}

class Product(IList<PriceBreak> priceBreaks)
{
  public IList<PriceBreak> PriceBreaks { get; } = priceBreaks;
}

Invocation Chain

var minPrice = product.PriceBreaks[0].Price;

As it’s written the preceding invocation chain is full of problems (we’ll ignore the potential ArgumentOutOfRangeException for this discussion). In fact, it can throw a NullReferenceException when any of the following values are null:

  • Product
  • Product.PriceBreaks
  • Product.PriceBreaks[0]

To properly avoid the exception we need to explicitly check for null. One possible approach would look like this:

double minPrice = 0;

if (product != null
    && product.PriceBreaks != null
    && product.PriceBreaks[0] != null)
{
  minPrice = product.PriceBreaks[0].Price;
}

Now we can be certain that we won’t encounter a NullReferenceException but we’ve greatly increased the complexity of the code. Rather than a single line, we have 5 that actually do something and of that, less than half are providing any value beyond making sure we don’t see an exception. C# 6.0’s null propagation operator (?) gives us the safety of checking for nulls while avoiding the verbose ceremony. The result is much cleaner and closely resembles the invocation chain shown earlier:

var minPrice = product?.PriceBreaks?[0]?.Price;

Introducing the null propagation operator allows us to chain each call while short-circuiting any nulls encountered along the way. In this case, the return type is double? (INullable) because anything preceding Price can be null. As such, we can either defer checking for null until we try to use the value or we can simply use the null coalescing operator with a default to coerce the type conversion as follows:

var minPrice = product?.PriceBreaks?[0]?.Price ?? 0;

One limitation of the null propagation operator is that it can’t work directly with delegate invocation. For instance, the following code is invalid:

var result = myDelegate?("someArgument");

Fortunately, there’s a workaround; rather than invoking the delegate directly as shown above, we can use invoke it via the Invoke method like this:

var result = myDelegate?.Invoke("someArgument");

The null propagation operator should eliminate a great deal of null reference checking code although I still believe F#’s approach of virtually eliminating null is superior. Honestly, my biggest concern about the null propagation operator is that it could encourage Law of Demeter violations but that’s a discussion for another day.