C#6: Collection Initializers

Patterns and Collection Initializers

Some of the cool parts of C# are pattern-based, rather than type-based as one might expect. For example, `foreach` does not need the enumerated type to implement `IEnumerable` in order to work, it just requires that it has a `GetEnumerator()` method. Another place where pattern-based compilation occurs that also happens to illustrate how useful this pattern-based approach can be is in collection initializers like this:

var list = new List<int> { 1, 2, 3, 4, 5, 6 };

When this gets compiled, for each value in the initializer the C# compiler1 looks for an `Add()` method on the collection type with an appropriate number of arguments of the appropriate types, which it then calls for that value. The benefit to using a pattern-based approach is that the compiler does not need to know about every possible compatible type up front or what `Add()` methods it might support. It only enforces that the type derives from `IEnumerable` and that it has an `Add()` method that matches the initializer values. This allows us to create a collection types that can support a variety of different ways to add values without needing the compiler to know our type will ever exist. For example, we could create a collection of names with `Add()` methods that take one or two strings and then initialize elements with either just the surname or first name and surname2.

var names = new NamesCollection
{
   "Jones",
   { "David", "Smith" },
   { "Daniel", "Smith" },
   "Smith"
};

Collection initializers in C#6

In C#6, a new collection initializer syntax has been added and the way the compiler interprets the existing syntax has been modified. Before we look at the newly added syntax, let us look at how the compilation of the existing syntax has been changed. To do so, consider a collection of `DateTimeOffset` values where we want to simplify adding dates and times from parsable string values. To support this we could implement an entire new type with the appropriate calls or we could derive from an existing collection type `List<DateTimeOffset>` and then implement a new `Add()` method to support `string`.

public class DateTimeOffsetList : List<DateTimeOffset>
{
    public void Add(string value)
    {
        base.Add(DateTimeOffset.Parse(value));
    }
}

Of course, not all collections are open for extension and creating new types for this is cumbersome since we want a list of `DateTimeOffset` we just happen to want to initialize it from another type. To get around sealed types and the need to implement wrapper types or derivations, VB.NET has supported using extension methods to expand the `Add()` options on a type. I like this idea since, in the previous example, our list is really still of `DateTimeOffset` and we want others to see it that way, we just happen to support adding `string` values; why should we be forced to use a different type for that? Alas ((Cue Top Gear voice style)), this feature was not included in C#…until now. As of C#6, this disparity between VB.NET and C# is no more; the compiler will use a matching `Add()` extension method in lieu of an appropriate `Add()` method on the type itself.

public static class Extensions
{
    public static void Add(this List<DateTimeOffset> list, string value)
    {
        list.Add(DateTimeOffset.Parse(value));
    }
}

Interestingly, this change to how C# resolves overloaded methods is very specific in that it only supports `Add()` extension methods and not extension methods in other pattern-based scenarios like `GetEnumerator`. I am not certain why this so, since I can imagine some cases where enumerating an existing non-enumerated type might be quite nice3, though I expect is is because it would not be clear what was going to get enumerated and therefore, the code would be ambiguous and hard to follow4. The `Add()` method usage in an initializer does not have this ambiguity as the compiler makes it clear if it found a suitable `Add` method that matches both the collection type and the type of the element being added.

Index Initializers

The other change to collection initializers in C#6 is the introduction of index intializer syntax. This new syntax is similar to the existing collection initializer syntax we have discussed, except that instead of using `Add()` methods, it uses indexers. With index-based collection initialization we can specify values for specific indices in a collection. This works for any indexer that a collection implements. Traditionally, we might initialize a `Dictionary<string,string>` using the `Add()` method pattern like this:

var pairs = new Dictionary<string, string>
{
    {"address","12 This Way, Anywhere"},
    {"name", "Bob Foo"},
    {"title", "Master of the universe"}
};

But with the index initializer syntax, we can make it clear that one string indexes the other to make this much more readable as:

var pairs = new Dictionary<string, string>
{
    ["address"] = "12 This Way, Anywhere",
    ["name"] = "Bob Foo",
    ["title"] = "Master of the universe"
};

I cannot speak for anyone else, but I think this really makes the code easier to read. Note, however, that this new index syntax cannot be mixed with traditional initializer syntax; for example, the following is invalid:

var pairs = new Dictionary<string, string>
{
    {"address","12 This Way, Anywhere"},
    ["name"] = "Bob Foo",
    ["title"] = "Master of the universe"
};

I think it is okay that they cannot be mixed. One way is using `Add()` method overload resolution to set values and the other is using indexers; these use different semantics and often have different implementations and connotations. By mixing them, the code becomes muddled and loses meaning; are we specifying records in a collection or are we mapping specific indexes to their records?

In Conclusion

Both of these changes to collection initialization are reasonably subtle. Of all the features C#6 brings us, these are perhaps going to be used the least. In fact, when I started writing this post I was unsure of their value. However, as I wrote and thought of usage examples, I came to the realisation that although they cater to perhaps infrequent scenarios, these changes to collection initializers each provide nice additions to the C# language. Index initializers remove a little ambiguity from the initialization of indexed collections, such as dictionaries, whereas the expansion of `Add()` method overload resolution to include extension methods reduces the number of frivolous types we have to create. In short, they allow us to write simpler, clearer code, and that is a beautiful thing.

  1. pre-C#6 []
  2. A contrived example to be sure, but illustrative none-the-less []
  3. Such as enumerating the lines from a file stream []
  4. Much clearer to write a `LineEnumerator` wrapper for `FileStream` and use it explicitly []

C#6: The nameof Operator

Before discussing the `nameof` operator in C#6, I want us to consider why `nameof` exists at all. So, let's head back ten years to the heady days of 2005.

Wayne's World Flashback

When version 2.0 of the .NET framework arrived, it transitioned the fledgling platform from a sketch of what might be to a fully-formed platform that could support ongoing and future desktop and web development. Since then, each release of the framework and its associated languages have added a variety of bells and whistles that simplify and enhance the way we develop. Among many of the concepts and types introduced by .NET 2.0 was `System.ComponentModel.INotifyPropertyChanged`, part of the enhanced data binding introduced to Windows Forms development. This interface turned out to be a workhorse and introduced many developers to a new problem; making sure the string that named a variable matched the name of an actual variable.

Now, you may well object to this claim since various versions of `ArgumentException` already demanded this of developers, but I think we both know that until our tooling got smarter (like FxCop and Resharper), many of us just did not fill that argument out if we could help it. After all, the stack trace would tell us where the crash happened, we could put something meaningful in the exception message, and keeping that variable name up-to-date after refactoring was a pain. With the advent of `INotifyPropertyChanged` the benefit of putting the variable name in a string started to outweigh the costs. Quickly, patterns emerged to try and simplify this, from dubiously performant uses of reflection to build-time code generation. As tools matured, we could get refactorings that took these strings into account and warnings that could shout at us if a variable was mentioned that didn't exist. Few of these were particularly elegant or entirely foolproof, and none were both1. In addition to `ArgumentException` and `INotifyPropertyChanged`, property names would be used for logging and debugging.

In the Name of Progress

There were calls for a new operator to accompany `typeof`; the new operator, `infoof`2 would provide the corresponding reflection information of a particular code construct (like `MethodInfo` or `PropertyInfo`), simplifying not just obtaining the name of something, but also any reflection operation involving that something. All this use and discussion of meta-information did not go unnoticed. Eric Lippert blogged about `infoof` and why it would be useful, why it was so difficult to implement, and indirectly foreshadowed where we would be today. However, amid the discusson, there was little action.

In 2012, .NET 4.5 brought us the `CallerMemberNameAttribute` type and its siblings, `CallerLineNumberAttribute` and `CallerFilePathAttribute`. These new attributes enabled developers to decorate method arguments, indicating that the appropriate piece of information was to be injected into that argument when the method was called. This fell short of an `infoof` operator, but it greatly simplified use of `INotifyPropertyChanged` (and `INotifyPropertyChanging`, introduced in .NET 3.5). Alas, argument exceptions, logging, debugging, and other uses of method, variable, and property names were left as they were, often leading to mismatched error messages, obscure data binding bugs, and other problems.

That changed in 2015 with the new releases of both .NET and C#, and the new `nameof` operator in C#6. The `nameof` operator is sublimely simple; in fact, its concept seems so obvious that it's a wonder it took so long to appear3. Using `nameof`, we can inject the names of variables, types, methods, events, and properties into all sorts of places at compile-time4, knowing that if we change the name, our refactoring tools can update all references with confidence. Not only that, but our intent is clear; we want the name of this thing to be here and not just some string that happens to look like the name of some thing. While the `nameof` operator does not replace `CallerMemberNameAttribute`, which so deftly simplified `INotifyPropertyChanged`5, it does simplify other scenarios like throwing `ArgumentException`, logging errors, and outputting debug information.

In Conclusion

When I first contemplated writing a whole blog entry dedicated to `nameof`, I thought it was too simple a feature to warrant such focus; now I have finished, I believe `nameof` to be entirely worthy of the attention. Along with the fantastic string interpolation in C#6, I believe `nameof` is one of the simplest and most useful additions to the C#6 language. Like many C# and .NET features we now take for granted, `nameof` is a beautifully simple concept that we will come to rely upon. I believe it will save us countless hours of fixing erroneous refactoring, arguing over coding style and code reviews, and head-scratching at spurious errors.

  1. IMHO []
  2. pronounced, "Info Of" []
  3. As is often the case in software development, we were all too busy discussing the most complex use-case we could think of rather than the one that really needed solving []
  4. unlike reflection-based solutions that do all the work at run-time []
  5. `nameof` does provide an alternative, more wordy alternative for that scenario []

C#6: Exception Filters

The for the last six1 releases the C# compiler has been keeping part of the .NET Framework secret from us2; exception filters. It turns out that the .NET Framework has supported exception filters since the very beginning, there was just no way to express them using C# until now.

C#6 adds the when keyword for use in try/catch blocks to specify exception filters. An exception filter is a predicate method that takes the thrown exception and returns true when the exception should be caught or false when it should not. If the filter says the exception should not be caught, the underlying system can continue to throw it.

This allows us to reduce the complexity in our code as we can put multiple catch statements with different filtering rules in the same try/catch block. This gives a switch-style approach to exception handling that is supported at the lowest level, reducing the need to rethrow exceptions (or to remember the difference between throw and throw exceptionVar;)3.

Here is a try/catch block showing an example of exception filtering:

Func<ArgumentException,string,bool> filterParameterName = (e,s) => e.ParamName == s;
try
{
    CallSomething("param1", "param2", "param3", "param4");
}
catch (ArgumentException ex) when (ex.ParamName == "param1")
{
    Console.WriteLine("Filtered: param1");
}
catch (ArgumentException ex) when (filterParameterName(ex, "param2"))
{
    Console.WriteLine("Filtered: param2");
}
catch (ArgumentException ex)
{
    Console.WriteLine($"Unfiltered: {ex.ParamName}");
}

Before I continue, I must state that this is a completely contrived example for demonstrable purposes; your filters would probably act on more than just the value of a string, the two filters shown would use the same code, and the handling would involve different things in each catch4.

Now, some things to note. First, the parentheses around the when condition are mandatory; you don't need to remember this as the compiler and syntax highlighting will remind you. Second, the content of the when condition must evaluate to bool; you cannot specify a lambda expression here. I am certain most of you already assumed that, but for some reason, I felt like that should be possible. However,  when is akin to if or while, so it makes sense that a lambda expression would not work.

The example above provides three different catch blocks for the exact same exception type, ArgumentException. Each filter is evaluated in the order specified, so, if CallSomething() threw an ArgumentException with ParamName set to param2, the when condition on the first catch would reject it, but the second filter would catch it and handle accordingly. A ParamName value filtered out of the first two catch blocks would fall into the last.

In conclusion

Exception filtering is a useful and simple concept that should help to make exception handling easier to write. While some kind of filtering could be achieved before using conditions and throw inside of catch blocks, this language support now means that exception handlers (the content of catch blocks) have a single responsibility and the catch statements themselves are entirely responsible for declaring what must be caught. It also means that the exception handling within the .NET framework can be entirely responsible for routing exceptions in C#-implemented applications.

Exception filters have been supported by VB.NET and .NET-supporting variants of C++ since the versions released alongside .NET Framework 1.1; now, as of C#6, they are supported by C# too.

  1. 1.0, 1.2, 2.0, 3.0, 4.0, 5.0 []
  2. Actually, it's been keeping several, but we can't have everything []
  3. The first rethrows the original exception with the stack unchanged, the second throws a new exception and resets the stack []
  4. otherwise, why filter? []

C#6: Support for .NET Framework 2.0 to 4.5

A colleague of mine, Eric Charnesky, asked me if C#6 language features would work in .NET Framework versions other than 4.6. I was pretty confident that the features were almost all1 just syntactical seasoning, I thought I would find out.

The TL;DR is yes, C#6 features will work when compiled against .NET 2.0 and above, with a few caveats.

  1. Async/await requires additional classes to be defined since the Task Parallel Library, `IAwaitable` and other types were not part of .NET 2.0.
  2. The magic parts of string interpolation need some types to be defined (thanks to Thomas Levesque for catching this oversight).
  3. Extension methods need the declaration of `System.Runtime.CompilerServices.ExtensionAttribute` so that the compiler can mark static methods as extension methods.

Rather than just try .NET 4.5, I decided to go all the way back to .NET 2.0 and see if I could write and execute a console application that used all the following C#6 features:

The code I used is not really important, though I have included it at the end of this post if you want to see what I did. The only mild stumbling block was the lack of obvious extension method support in .NET 2.0. However, extension methods are a language-only feature; all that is needed to make it work is an attribute that the compiler can use to mark methods as extension methods. Since .NET 2.0 doesn't have this attribute, I added it myself.

Exclusions

You might have noticed that I did not verify a couple of things. First, I left out the use of `await` in `try`/`catch` blocks. This is because .NET 2.0 does not include the BCL classes that the compiler expects when generating the state machines that drive async code. You might be able to find a third-party implementation that would add support, but my brief3 search was fruitless. That said, this feature will definitely work in .NET 4.5 as it is an update to how the compiler builds the code.

Second, I did not intentionally test the improved overload resolution. The improvements mostly seem to relate to resolution involving overloads that take method groups and nullable types. Unfortunately, in .NET 2.0 there was were no `Func` delegate types nor nullable value types (UPDATE: Nullable types totally existed in .NET 2.0 and C#2; thanks to Thomas Levesque for pointing out my strange oversight here – I blame the water), making it difficult to craft an example that would demonstrate this improvement. However, overload resolution affects how the compiler selects which method to use for a particular call site. Once the compiler has made the selection, it is fixed within the compiled output and as such, the version of the .NET framework has no bearing on whether the resolution is correct4.

Did it work?

With the test code written, I compiled and ran it. A console window flickered and Visual Studio returned. The code had run but I had forgotten to put anything in there that would give me chance to read the output. So, I dropped a breakpoint in at the end, and then ran it under the debugger. As I had suspected it might, everything worked.

Testing under .NET 2.0 runtime on Windows XP
Testing under .NET 2.0 runtime on Windows XP

Then I realised I was still executing it on a machine that had .NET 4.6 and therefore the .NET 4 runtime; would it still work under the .NET 2 runtime? So, I cracked open5 a Windows XP virtual machine from modern.ie and ran it again. It didn't work, because Windows XP did not come with .NET 2.0 installed (it wasn't even included in any of the service packs), so I installed it and tried once more. As I had suspected it might, everything worked.

In conclusion

If you find yourself still working with old versions of the .NET framework or the .NET runtime, you can still use and benefit from most features of C#6. I hope my small effort here is helpful. If you have anything to add, please comment.

Here Lies The Example Code6

using System;
using System.Collections.Generic;
using static System.Math;

namespace System.Runtime.CompilerServices
{
    [AttributeUsage( AttributeTargets.Method )]
    public class ExtensionAttribute : Attribute
    {
    }
}

namespace CSharp6andNET2
{
    internal class Program
    {
        public delegate bool Filter( ArgumentException ex, string argName );

        public bool DoFilter( Filter test, ArgumentException ex, string argName )
        {
            return test( ex, argName );
        }

        private static void Main( string[] args )
        {
            Filter x = ( ArgumentException ex, string argName ) => ex.ParamName == argName;
            for ( int count = 0; count < 2; count++ )
            {
                try
                {
                    ExceptionFilterTest( count == 0 );
                }
                catch ( ArgumentException e ) when (x( e, "argumentName" ))
                {
                    Console.WriteLine( "Logged filtered exception" );

                    var test = new TestClass();
                    Console.WriteLine(
                        $"{nameof( test.Count )}: {test.Count}, {nameof( test.Count2 )}: {test.Count2}{nameof( test.Count3 )}: {test.Count3}, {nameof( test.Count4 )}: {test.Count4( 1 )}" );

                    var list = new List<int>
                    {
                        "9",
                        "25",
                        "36",
                        16,
                        4,
                        64
                    };

                    Console.WriteLine( "List" );
                    foreach ( var n in list )
                    {
                        Console.WriteLine( Sqrt( n ) );
                    }

                    var dictionary = new Dictionary<int, string>
                    {
                        [ 4 ] = "Test",
                        [ 2 ] = null,
                        [ 45 ] = null,
                        [ 34 ] = null,
                        [ 200 ] = null,
                        [ 16 ] = "Another test"
                    };

                    foreach ( var k in dictionary )
                    {
                        Console.WriteLine( $"{k.Key}: {k.Value?.Substring( 0, 3 )}" );
                    }
                }
                catch ( Exception )
                {
                    Console.WriteLine( "Logged exception" );
                }
            }
        }

        private static void ExceptionFilterTest( bool filterable )
        {
            if ( filterable ) throw new ArgumentException( "Exception", "argumentName" );

            throw new Exception( "Exception" );
        }
    }

    internal static class Extensions
    {
        public static void Add( this List<int> list, string value )
        {
            list.Add( Int32.Parse( value ) );
        }
    }

    internal class TestClass
    {
        public int Count { get; } = 6;
        public int Count2 { get; set; } = 6;
        public int Count3 => 6;
        public int Count4( int x ) => x + 6;
    }
}

 

  1. Async/await requires the TPL classes in the BCL, extension methods need the ExtensionAttribute, and exception filters require some runtime support []
  2. The Elvis's []
  3. very brief []
  4. I realise many of the C#6 features could be left untested for similar reasons since almost all are compiler changes that do not need framework support, but testing it rather than assuming it is kind of the point []
  5. Waited an hour for the IE XP virtual machine to download and then get it running []
  6. Demonstrable purposes only; if you take this into production, on your head be it []

C#6: String Interpolation

Continuing the trend of my recent posts looking at the new features of C#6, this week I want to look at string interpolation.

Prior to C#6, string interpolation (or string formatting) was primarily the domain of the .NET framework and calls like `string.Format()` and `StringBuilder.AppendFormat()`1 as in the following example:

var aString = "AString";
var formatString = string.Format("The string, '{0}', has {1} characters.", aString, aString.Length);

With string interpolation in C#6, this can be written as:

var aString = "AString";
var formatString = $"The string, {aString}, has a {aString.Length} characters.";

This is a little easier to read while also reducing what has to be typed to achieve the desired result. The contents of the braces are evaluated as strings and inserted into the resultant string. Under the hood, this example compiles down to the same `string.Format` call that was made in the earlier example. The same composite formatting power is there to specify things like significant figures and leading zeroes. If you need a culture-invariant string, there is a handy static method in the new `System.FormattableString` class called `Invariant()`. If you wrap your string with this `Invariant()` method, you will get the string formatted against the invariant culture.

Magic

Of course, to end the story there without discussing the compiler magic would do a disservice to this new feature. In the example above, the result of the interpolation was stored in a variable with type `var`. This means the type is inferred by the compiler, which infers `string` and then performs appropriate compiler operations to turn our interpolated string into a call to `string.Format()`. This means that we don't have to do anything else to use this feature and get formatted strings. However, we can make the compiler do something different by rewriting the line like this2:

FormattableString formatString = $"The string, {aString}, has a {aString.Length} characters.";

We have now specified that we are using a variable of type `FormattableString`. With this declaration, the compiler changes its behavior and we get a `FormattedString` object that represents the interpolated string. From this object, we can get the `Format` string that could be passed to a call that takes a format string, such as `string.Format()` (there are several others in types like `Console`, `StringBuilder`, and `TextWriter`). We can also retrieve the number of arguments3 in the string using `ArgumentCount`, and use `GetArgument()` and `GetArguments()` to retrieve the values of those arguments. Using a combination of `Format` and `GetArguments()`, we can pass this information to a different call that might reuse or extend it to produce a different message. Finally, we can use the `ToString()` call to specify an `IFormatProvider`, allowing us to format the string according to a specific culture.

By telling the compiler that we want a `FormattableString` we get all this extra information to use as we see fit. If you look at the arguments using either of the `Get..` methods, you will see that the values have already been evaluated, so you can be assured that they won't change as you process the string. I'm sure there are situations where you might find this additional access to the formatting invaluable, such as when creating compound error messages, or perhaps doing some automatic language translation.

In conclusion…

There's not much else for me to say about C#6's string interpolation except to highlight one gotcha that I have hit a couple of times. The next two examples should illustrate appropriately:

Console.WriteLine($"{DateTime.Now}: I'm writing DateTime.Now to the console");
Console.WriteLine("{DateTime.Now}: I'm writing DateTime.Now to the console");

Here is what these two examples will output:

9/8/2015 11:11:43 AM: I'm writing DateTime.Now to the console.
{DateTime.Now}: I'm writing DateTime.Now to the console.

It's hard to argue with either of them, after all, they both wrote an interpretation of `DateTime.Now` to the console, but the first one is perhaps a more useful output4.

So why did the second example not work? You may have already spotted the answer to that question, especially if you're a VB programmer; it's the `$` at the start of the first example's string.  This `$` tells the compiler that we are providing a string for interpolation. It's an easy thing to miss and if you forget it (or perhaps, in rare cases, add it erroneously) you'll likely only spot the mistake through thorough testing5 or customer diligence6. As always, learn the failure points and work to mitigate them with code reviews and tests. I suspect the easiest mitigation may be to always use the interpolation style strings unless a situation demands otherwise.

And that's it for this week. What do you think of the new string interpolation support? Will you start using it? If not, why not? Do you have any cool ideas for leveraging the additional information provided by `FormattableString`? Please share in the comments.

If you're interested in my other posts on some of the new things introduced by C#6, here are links to posts I have written thus far:

  1. The `+` operator can be used in conjunction with `ToString()` but it can get messy to read and is very hard to localize []
  2. We could also cast the interpolated string to `FormattableString` and leave the variable as `var`. []
  3. Each inserted value is an argument []
  4. Except when providing examples in a blog []
  5. Unit tests or otherwise []
  6. Write automated tests and test manually; let's not use customers as QA []