C# 6.0 Features

C# 6.0 Features
   C# 6.0 has been officially released along with the Roslyn compiler platform. I feel it is my duty to inform the world of my opinion on the topic as undoubtedly millions are interested to learn what they should think about it. Adopting mine is the easiest way to have a correct opinion.

   The Roslyn compiler platform is surely more important than the set of features in this release of C#. Roslyn has effectively turned the C# compiler into a library with a reasonable API that a lot of developers can use to build cool features with the full power of the compiler behind them. The obvious example is an IDE editing support but there are many other cool things like C# scripting or services like .NET Fiddle. ASP.NET is also benefiting as the save and refresh support is built on Roslyn.

   My favorite feature built on top of Roslyn is Code-aware libraries. Code-aware libraries allow the library author to provide analyzers that plug into the compiler and produce errors and warnings when they detect incorrect use of the library. For example you may build an analyzer to check if the developer forgot to call Dispose() on a Disposable type and also verify that the instance is created in the same method. In the link above Microsoft gives an example with using the default constructor on an ImmutableArray (which must have one since it is a struct) which the analyzer will catch. These analyzers can easily integrate with the build system as well and provide text suggestions and even automatic fixes in the IDE all thanks to Roslyn. I do not doubt that in the future we will see even cooler and more creative usages of Roslyn.

   So what is new in the C# language itself?

Auto Property Initializers, Read-only Auto Properties, Constructor Assignment for Read-only Auto Properties


   Automatic properties were introduced in C# 3.0. This is the official name for this thing you write with empty get and set:

public class Customer
{
   public string Name { get; set; }
}

   In C# 6 they can be initialized like this

public class Customer
{
   public string Name { get; set; } = "Stilgar";
}

   This opens the door for another related feature read-only auto properties

public class Customer
{
   public string Name { get; } = "Stilgar";
}

   This is great for creating immutable types. Of course the proper place to assign a field is in the constructor and C# 6.0 supports assigning read-only auto properties in the constructor and only in the constructor.

public class Customer
{
   public string Name { get; }
   public Customer(string name)
   {
       Name = name;
   }
}

To achieve similar behavior I used to write private setters. While this worked OK the new way is cleaner, prevents mutating the field in another method and generates readonly field which may be used by the compiler and/or the JIT compiler to generate more efficient code. As far as I know such optimizations do not currently exist but who knows what the future holds. Overall small improvement but one I can use multiple times every day. It is tied with the nameof operator for my favorite C# 6.0 feature.

Static Imports


   Static imports allows importing a static class via a using directive and calling its static methods without the class name. The example that is given often is

using System.Console;

public class Program
{
   public static void Main()
   {
       WriteLine("Hello World");
   }
}

However I dislike this usage. Console is exactly the type of class that should be mentioned by name when calling its static methods. A proper example will be the Math class which contains mathematical functions. Static import makes static methods look like functions and math functions are the most obvious candidate. We all know that Sin is a function so why not use it like one? The Console example suggests that the feature may be abused but it has existed in Java for decades and it was used reasonably so there is no reason to expect the average developer would actually import Console and the advantage for mathematical code is too great to miss.

Index Initializers


   Index initializers are just part of object initializers. Since C# 3.0 one could initialize an object like this:

var c = new Customer { Name = "Anders" };

With C# 6 one could also set values via an indexer. The example is a JObject from the JSON.NET library

new JObject { ["x"] = 3, ["y"] = 5 };

This is not extremely useful but it makes the object initializer feature more complete. It is logical that if you could set properties like this you can also set indexers. In my opinion this feature makes the language simpler by making it more predictable.

Await in catch/finally


   This one is pretty straight-forward. You can now use await in a catch or finally block. The C# team could not finish this for the previous release so they are adding it now. After tasting the sweet drug known as async/await it was almost painful to downgrade to raw tasks just because your fallback code needed to make another network request. I will be fixing some of this type of code in existing projects.

Exception filters


   I had quite a bit of trouble understanding why this feature exists. It allows you to conditionally catch the exception like this:

try
{
   //throw exception
}
catch(SomeException ex) when (ex.SomeProperty > 10)
{
  //handle the exception
}

The catch block will only execute if the boolean expression evaluates to true. I had trouble understanding why this feature was needed. After all I thought the following code would do the same

try
{
   //throw exception
}
catch(SomeException ex) when (ex.SomeProperty > 10)
{
   if(ex.SomeProperty > 10)
   {
       throw;
   }
   //handle the exception
}

The throw statement preserves the StackTrace property (as opposed to throw ex) so what is the problem? The problem is that throw really preserves the StackTrace property and not the call stack itself. If the program crashes the debugger will see the throw as the point of failure and memory dumps will also show the state in the catch block. By contrast exception filters that do not match preserve the call stack as it is and this can be quite useful when debugging extreme cases.

Expression-bodied Members


   Expression-bodied members allow programmers to define properties and methods via expressions (almost identical to lambda expressions). This is the only feature I am not sure I like. It provides an alternative syntax for defining members while the current one is already good enough and well-known. However in the light of features coming in C# 6.0 and more specifically record types this might make more sense. The idea of the record types is to be very concise so this syntax will fit nicely. Here is what they look like:

public class Customer
{
   public string FirstName { get; set; }
   public string LastName { get; set; }
   public string FullName => FirstName + " " + LastName;
   public string GetNameWithTitle(string title) => title + " " + FullName;
   public string GetNameWithMr() => GetNameWithTitle("Mr.");
}

Note that FullName is a get-only property while GetNameWithMr is a method. The difference is the use of () parameter list on the method. I think I will not be using this feature the same way I do not use single statement ifs and loops without parenthesis but who knows. When I try it in real world code I might change my mind. For comparison here is the C# 5.0 version of the code above formatted in the way I would format it in a real world project:

public class Customer
{
   public string FirstName { get; set; }
   public string LastName { get; set; }

   public string FullName
   {
       return FirstName + " " + LastName;
   }

   public string GetNameWithTitle(string title)
   {
       return title + " " + FullName;
   }

   public string GetNameWithMr()
   {
       return GetNameWithTitle("Mr.");
   }
}

Monadic Null Checking


   Monadic Null Checking is officially called Null-conditional Operator but Monadic Null Checking certainly sounds cooler. The feature amounts to using ?. rather than . to access members. When accessed like this the compiler inserts a null check and so you do not get a NullReferenceException if the value is null. The return value of a method called on null is null. Return types that cannot be null are promoted to nullable types.

   int? firstNameLength = customer?.FirstName?.Length;

Ideally one would not need to use this feature. In most cases some form of null object is much better than null value. Consider an IEnumerable collection. If the collection is empty one should instantiate it with an empty enumerable rather than leave it null. This way method calls would work. Of course some APIs require a lot of work to introduce a null object and others are simply out of our control. Therefore the operator is useful but one should be careful to use it sparingly and not leave IEnumerable null simply because the operator exists.

   One cool use of this feature is calling delegates for events which should always be checked for null anyway.

Click?.Invoke(this, EventArgs.Empty);

And yes, the compiler will do this in a thread-safe manner. The equivalent C# 5.0 code is

var temp = Click;
if(temp != null)
{
   temp(this, EventArgs.Empty);
}

The temp variable is needed to prevent race conditions when a client unsubscribes.

String Interpolation


   String interpolation gives the ability to embed expressions directly into string literals.

Console.WriteLine($"Customer {customer.FullName} born on {customer.DateOfBirth:D} has made {customer.Orders.Count} orders");

Note the ability to use expressions and format specifiers. The format specifiers are the same as those used by String.Format and string interpolation compiles to String.Format.

   The common complaint about string interpolation is that you cannot distinguish code from the literal string but Visual Studio colors the embedded expression like it colors normal code while the actual literal is colored as a string literal. In my opinion this is quite readable.

Operator nameof


   One of my two favorite features. The operator nameof accepts an identifier and returns the string that is the identifier. Of course you can just write the string rather than using nameof but then there is a risk that someone might change the name of the identifier. MSDN lists a lot of scenarios where this is useful but probably the most popular one is INotifyPropertyChanged implementation

int SomeProperty
{
   get { return someProperty; }
   set
   {
       someProperty = value;
       PropertyChanged(this, new PropertyChangedEventArgs(nameof(SomeProperty));
   }
}

The interesting part of this feature is that it is very hard to emulate. Current solutions include the use of lambdas and expression tree parsing to get the name of the item. This operator will make things much easier.

Disable Warnings Enhancements


   I was quite confused about this feature since C# always had the ability to disable warnings via a #pragma directive. I had to ask on Stack Overflow to understand what the feature means. With Jon Skeet himself to the rescue it is now clear to me and the rest of the world that they enabled string identifiers for the warnings as opposed to only numbers. This is important because code aware libraries will introduce a lot of new warnings so the numbers may collide. In theory libraries will prefix their warnings uniquely.

Extension Add in Collection Initializers


   As you should know collection initializers look for an Add method on the object and call it with the specified values. Now the Add method can also be an extension method. I have no idea where the need for this comes from but it seems to make the language more consistent.

Improved Overload Resolution


   In certain cases C# will be able to choose an overload where before you would get an overload resolution error. Basically developers will become more productive without even noticing.

   Instead of conclusion I want to add how pleasantly surprised I was by the evolution of the feature design. Almost all proposals I disliked were either dropped or transformed into something I like. The only exception is the expression-bodied members and I did not feel very strongly about them. I disliked primary constructors a lot and was happy to see them removed. Now they may come back in the form of records but this is quite different and I am all for adding records and pattern matching to C#. Some nice features like declaration expressions and IEnumerable params were sadly dropped but I think it is a good trade off. A bad feature that makes it in needs at least 10 good features to balance the damage. Overall a great release that I cannot wait to use in production.

   Well that was quite a long article but with such an important release there was no other way.
Tags:   english programming 
Posted by:   Stilgar
22:12 30.07.2015

Comments:

First Previous 1 Next Last 

Posted by   JOke (Unregistered)   on   18:56 03.08.2015

biva

Posted by   Стойчо (Unregistered)   on   21:02 04.08.2015

Става

Posted by   Genata (Unregistered)   on   21:20 04.08.2015

Vaji

Posted by   Guest (Unregistered)   on   21:55 04.08.2015

Ne e zle

Posted by   Guest (Unregistered)   on   23:45 04.08.2015

Biva

Posted by   sve   on   14:43 05.08.2015

Hell, it's about time

First Previous 1 Next Last 


Post as:



Post a comment: