Learning C# by Example

What's new in C# 6.0

What's new in C# 6.0? Roslyn, Auto-Property Initializers, Read-only auto-properties, Expression Bodies, Null-Conditional, String Interpolation, nameof, Index Initializers, Exception Filters and await changes.

C# 6.0 does not bring any major changes to the outward appearence of the language, but has some nice "syntactic sugar" to make life easier.

  1. Roslyn

    The biggest change is the Roslyn compiler. Roslyn is now open-source and hosted at github. It provides API hooks so tool builders can harness its power. Roslyn is a complete rewrite of the compiler and its aiming for platform independence. It should allow for easier compile-on-the-fly code so C# can be used as a Domain Specific Language (DSL).

  2. Auto-Property Initializers (Auto-Implemented Properties).

    Properties can be initialized just like fields. These are initialized by accessing the backing field of the property directly. Below the Property "Pet" has a default name of "Unknown".

     
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace SeaSharpSix
    {
        class VetHospital
        {
    
            static void Main(string[] args)
            {
                var pet = new Pet();
                Console.Out.WriteLine("pet.name = {0}", pet.Name); //"Unknown"
                Console.In.ReadLine();
            }
    
            public class Pet
            {
                public string Name { get; set; } = "Unknown";
            }
        }
    }
    
  3. Read-Only Auto-Properties

    By omitting "set", a Property by default becomes "readonly" and can only be set in the initializer and the constructor.

     
     public class Pet
     {
         public string Name { get; } = "Rover";
     }
    
  4. Expression Bodied Method-Like Members

    You can use the "=>" rocket symbol to define a method like a lambda expression.

     
    public string Info() => Name + " was born on " + Birthdate.ToLongDateString();
    
  5. "using static" directive

    This will make the imported static class members come into scope. This makes the code less verbose, but can make it harder to understand.

     
    using static System.Console;
    ...
    WriteLine("pet.Info() = {0}", pet.Info()); //you can skip the "System.Console." prefix
    
    
  6. Null-Conditional Operator

    This is my second favorite feature in 6.0. You compress all those null checks, e.g., "if(list != null && list.First() != null)" into something terse by using "?".

     
    var firstName = list?.First()?.Name;
    
  7. String Interpolation

    This is my favorite new feature. You replace the '{n}' in a string.format with the actual variable name. Be sure to preface the string with '$'. The two lines below are equivalent.

     
    Console.Out.WriteLine("My pet '{0}' was born on {1}.", pet.Name, pet.Birthdate.ToLongDateString()); 
    Console.Out.WriteLine($"My pet '{pet.Name}' was born on {pet.Birthdate.ToLongDateString()}."); 
    
  8. "nameof" expression

    This allows for the actual name of a program element to be used. We could do the same thing with string literals, but during refactoring the variable name could be changed, making an error message outdated. During compilation the value of the "nameof" argument will be converted to a string literal. The compiler will warn you if no variable has the name in "nameof".

     
    var pet = new Pet();
    pet.Birthdate = DateTime.Now.AddYears(2);
    if (pet.Birthdate > DateTime.Now)
    {
        WriteLine("Bad value for "+nameof(pet.Birthdate)); //writes 'Birthday'
    }
    
  9. Index Initializers

    Dictionaries can now use index initializers.

     
     months = new Dictionary<int, string>
    {
        [0] = "jan",
        [1] = "feb",
        [2] = "mar"
    };
    
  10. Exception Filters

    You can attach a boolean expression after a catch. The catch block is only executed if the boolean expression is true. For example, in the code below the output is "condition = 3".

     
    int condition = 3;
    try
    {
       throw new Exception();
    }
    catch (Exception e) when (condition == 2)
    {
        Out.WriteLine("condition = {0}", condition);
    }
    catch (Exception e) when (condition == 3)
    {
        Out.WriteLine("condition = {0}", condition);
    }
    
    
  11. 'await' can be now be used in 'catch' and 'finally' blocks
     
      private static async Task GetPage()
         {
             HttpClient client = new HttpClient();
             try
             {
                 var page = await client.GetStringAsync("https://www.fincher.org");
                 WriteLine(page);
             }
             catch (Exception exception)
             {
                 var page = await client.GetStringAsync("https://www.fincher.org/error");
                 WriteLine(exception + page);
             }
            }