Author: Dave Fancher

Dave Fancher is a Software Engineer at Performance Assessment Network in Carmel, Indiana, a Microsoft MVP for Visual F#, and author of The Book of F# from No Starch Press. He has been building software with the .NET Framework since version 1.1. Dave is active within the Indiana software development community as a member of IndySA, a speaker at user groups throughout the state, and a two-time contributor to Indy GiveCamp. When not writing code he enjoys spending time with his family, watching movies, photography, and gaming on on his Xbox One.

Musings on C#’s Evolution

Since completing my series on likely C# 6.0 features and reviewing the draft spec for record classes and pattern matching in C#, I’ve had some time to reflect on how C# has evolved and think about where it’s going from a more holistic perspective.

I’ve been working with C# for approximately 12 years. It was the language of choice at the beginning of my career so, in a sense, C# and I have grown up together. During that time I’ve watched what was essentially a Java clone grow into the powerhouse it is today. It’s a bit cliché, but when I started working with C# it didn’t have many of the features I now take for granted. Things like generics, the null coalescing operator, lambda expressions, extension methods, anonymous types, dynamics, and async/await were in their infancy with some as much as a decade away. It seems that every major release has brought a slew of compelling new features that have dramatically improved the language.

As I look at the code I write today I often wonder how C# developers managed without generics. I remember the headaches of dealing with ArrayList and its early kin and having to trust that the objects in the collections were actually the types we thought they were. Today I often look at blocks of imperative code (typically loops) that see that they’re doing nothing more than explicitly filtering, mapping, and reducing sequences. I immediately think how much cleaner the code would be with LINQ. And in today’s world of connected mobile devices where application responsiveness is of primary importance, async/await make asynchronous development accessible to the masses. These are all incredible tools we have at our disposal and are all among the reasons I’ve stuck with .NET development for so long.

C# 6 is different. With C# 6, the language enhancement is the Roslyn compiler. Roslyn promises to bring modern compilation strategies to C#. This is a huge undertaking and heavily impacts how we’ll interact with code through Visual Studio and other tools. I haven’t looked at Roslyn nearly as much as I’d like but I do believe the new compiler is long overdue and will pay dividends in the long run for developers and Microsoft alike. That said, the actual changes to the C# language itself seem to range from lackluster to pointless.

I’m not saying that the language features are all bad; several of them will likely be welcome additions to the language. Enhancements such as primary constructors, auto-implemented property initializers, and using static are each things that can have an immediate impact on developer productivity and are by far my favorites of the lot. Other features, such as index initializers, params IEnumerable<T>, and expression-bodied members don’t really seem to add much to the language due to either existing syntactic constructs or other limitations of the language.

Is initializing dictionary elements with [7] = "seven" really any better than with { 7, "seven" }? All the index initializer achieves is trading a pair of curly braces and a comma for a pair of square brackets and an assignment operator, respectively. How is params IEnumerable<int> better than params int[] if the argument list is still converted to an array at the call site and no other usage requires defining the parameter with the params modifier? Finally, expression-bodied members could be a great feature if C# was an expression-based language but it’s not – it’s statement-based. The proposed semicolon operator could greatly increase the usefulness of expression-bodied members but at the time of this writing, it’s still listed as “Maybe” on the Language Feature Implementation Status page. Even then, the semicolon operator feels like an attempt to coerce C# into being expression-based when it was never intended to be treated as such. In the meantime, there’s already a perfectly viable alternative – write a function!

Looking further into the future brings us to the draft spec for record classes and pattern matching. (Please note that since this spec is a draft, everything here is subject to change; whatever does get implemented, if anything, may or may not look like this proposal.) If you haven’t read the draft (and I highly recommend that you do), it proposes a new record modifier for class definitions. This modifier would instruct the compiler to generate an immutable class with built-in structural equality and an is operator (if not provided). The is operator can then be used in if and switch statements for type checking and value extractions.

For example, we could define a class like this (example taken from the proposal):

public record class Cartesian(double x: X, double y: Y);

…then use pattern matching constructs like this (adapted from the proposal):

if (expr is Cartesian c)
{
  // code using c
}

My initial reaction when I heard about these features was excitement but the more I read and the more I think about it, the less I like them, pattern matching in particular. I’ll be the last person to argue against immutability and pattern matching, especially when looking at them from a functional programming mindset. I do like the simplicity of the immutable record classes and I don’t mind that pattern matching is essentially an extension of the is operator.

The reason I don’t like these features as proposed is that they don’t feel like they belong in C#. I feel like this for a few reasons. First, pattern matching can improve code’s expressiveness but merely adding it to a language that wasn’t constructed with pattern matching in mind severely limits its usefulness. Second, the overall expressiveness is again limited by the fact that C# isn’t an expression-based language; pattern matching might make if statements and switch statements more concise, it doesn’t change the fact that they’re still statements!

Let’s contrast the proposal with an expression-based language where pattern matching is already a central concept: F#. As an expression-based language, virtually everything in F# is an expression. This includes familiar constructs like ifs and matches. By definition, as expressions these constructs return values – there’s no need to rely on mutability or wrap the behavior within a separate function, returning from each branch as we must in a statement-based language. For example, this is valid F#:

let x = if System.Random().Next(10) % 2 = 0 then "even" else "odd"

You could correctly argue that C# provides the conditional operator for this scenario but that doesn’t change the fact that in C#, if is a statement whereas in F# it’s an expression. Furthermore, what’s probably not apparent here if you’re not familiar with F# is that binding x is a pattern match. You can see this in action by replacing x with an underscore (F#’s wildcard pattern matches everything and tosses out the result) as follows:

let _ = if System.Random().Next(10) % 2 = 0 then "even" else "odd"

If you evaluate the expression in F# Interactive (FSI) you’ll see that it executes successfully but no value is bound as we’d expect due to the wildcard. For further proof, this is also how tuple binding works as evidenced here:

let value, category =
  let r = System.Random().Next(10)
  r, if r % 2 = 0 then "even" else "odd"

The expression following the assignment in the above snippet returns a tuple containing a random value and whether that value is even or odd. The tupled items are then bound to value and category respectively by using pattern matching.

Pattern matching completely permeates F#. It’s not restricted to match expressions or inline bindings; it even works in function signatures and as a filter in looping constructs! The C# proposal doesn’t talk about pattern matching outside the context of if statements and switches so discussing whether C# will embrace pattern matching as fully as F# is pure speculation but it certainly doesn’t sound particularly promising at this point. Even if pattern matching is supported outside of if and switch statements, it’s still the same underlying statement-based language.

My point in writing all of this is that for years C# has been becoming increasingly functional, with the strongest push coming in version 3 and subsequent releases building upon that foundation. Many of the features in C# 6.0 continue even further down that path by elevating expressions an even more important concept within the language. Finally, a future incarnation of the language will likely include some form of immutable class syntax and pattern matching. If this is the direction that C# is going, my question is this: Why wait for it? Why not learn a functional language to at least supplement the object-oriented language you already know?

The C# of the future is already here and it’s called F#. F# already has a modern compiler; it already supports many of the things slowly making their way into C# and much, much more. In other words, there’s no reason to wait for these things to make it into C# because F# already does them! Incorporating F# into your existing solutions isn’t a mutually exclusive proposition. As a CLR language, F# compiles to the same IL, targets the same runtimes (with few exceptions), and uses the same libraries with which you’re already familiar. In many cases it’s a perfect complement to or replacement for existing C# code.

I challenge you to try F#. Experiment with the features; see how many things you can spot that are “recent” additions to C#, making their way to C#, or not possible at all. I think you’ll be pleasantly surprised at how adopting an expression-based, functional-first language can change the way you think, improve the quality of your code, and make you more productive. If you accept this challenge, I recommend checking out my book or any of the great resources listed on my Learning F# page to get you started.

Community Calendar – IndySA – September 18

IndySA is on a roll with great speakers. This month, Phil Japikse will lead the group in an interactive workshop covering user story mapping. If you want to improve your user story organization and prioritization skills, you won’t want to miss this one as Phil will guide the group through creating a user map, clearly defining order, minimal marketing features, and release plans.

I’ve been fortunate to attend a number of Phil’s previous talks and had have always learned something. You can register and find full logistics information by following the link below.

Register Here

I hope to see you there!

IndyMobileDev Needs Your Help

The Indianapolis Mobile [.NET] Developers Meetup group needs your help. We’ve received a number of interesting topic submissions including TypeScript, Responsive Design, and Single Sign-On. Rather than arbitrarily selecting topics, we’ve put together a short survey to help us gauge interest in each of the submitted topics. If you could take a moment to complete the survey, you’ll help us prioritize topics for future meetings and ensure that the group continues to be a valuable resource for the community we serve.

TAKE THE SURVEY

Thank you for your time.

C# 6.0 – Expression-bodied Members

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

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

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.