Srikanth Technologies

What's New In C# 6.0

The following are new features of C# 6.0. 

Nothing ground-breaking. But it is about a couple of minor changes that make the language easier to use.  These are features added to C# 6.0, which was released in 2015 and included in .Net 4.6.

Here is the list of features that I cover in this blog:

Importing static members

It is possible to use static keyword in using statement to import static members of a class. This eliminates the need to qualify static members of a class with classname.

using static System.Console;    // Import all static members of Console class
using static System.DateTime;   // Import all static members of DateTime class

namespace Csharp6_features
{
    class StaticUsing
    {
        public static void Main()
        {
            WriteLine("Hello!");  // we don't have to use Console.WriteLine anymore
            WriteLine(Today);
        }
    }
}

Initializing Auto Implemented Properties

It is now possible to initialize auto implemented properties at the time of creating properties.

using static System.Console;
using static System.DateTime;

namespace Csharp6_features
{
    class AutoInitProperty
    {
        public static void Main()
        {
            MyTime t = new MyTime();
            WriteLine("{0}:{1}:{2}", t.Hours, t.Mins, t.Secs);
        }
    }
    class MyTime
    {
        public int Hours { get; set; } = Now.Hour;     // set Hours property to value of given expression
        public int Mins { get; set; } = Now.Minute;
        public int Secs { get; set; } = 0;             // set Secs property to 0
    }
}

String Interpolation

It is possible to use variable as part of string by enclosing variable in braces ({}). For this to work the whole string should be prefixed with dollar ($).

using System;

namespace Csharp6_features
{
    class StringInterpolation
    {
        public static void Main()
        {
            string name = "Anders";
            int age = 55;

            // Before C# 6.0
            Console.WriteLine("Name : {0}, Age : {1:D2}", name, age);

            // In C# 6.0
            Console.WriteLine($"Name : {name}, Age : {age:D2}");
        }
    }
}

New way to initialize Dictionary

It is possible to initialize dictionary by enclosing key in square brackets ([]) and value after = sign, for each pair.

The following code shows how it was done before C# 6.0 and how it can be simplified in C# 6.0.

using System;
using System.Collections.Generic;

namespace Csharp6_features
{
    class DictionaryInit
    {
        public static void Main()
        {
            // Before C# 6.0
            var products = new Dictionary<string, double>()
            {
                { "iPhone", 60000 },
                { "iMac", 90000 },
                { "iPad", 45000 },

            };
            foreach (var prod in products)
            {
                Console.WriteLine($"{prod.Key} - {prod.Value}");
            }

            // In C# 6.0
            var products2 = new Dictionary<string, double>()
            {
                ["iPhone"] = 60000,
                ["iMac"] = 95000,
                ["iPad"] = 45000
            };
            foreach (var prod in products2)
            {
                Console.WriteLine($"{prod.Key} - {prod.Value}");
            }
        }
    }
}

Expression Bodied Functions and Properties

It is now possible to create a function that is associated with just lambda expression and no body. For simpler functions, we can provide body using lambda expressions instead of body block.

using System;
namespace Csharp6_features
{
    class ExpressionBodiedFunction
    {
        public static int Add(int n1, int n2)
        {
            return n1 + n2;  // old way of doing it
        }

        public static int Mul(int n1, int n2) => n1 * n2;  // Possible in C# 6.0
        
        public static void Main()
        {
            Console.WriteLine(Add(10, 20));
            Console.WriteLine(Mul(10, 20));
        }
    }
}

Exception Filtering

Exception handling can be conditional. Whether a catch block handles exception can depend on a condition given after catch using when keyword followed by condition.

The following is general syntax of catch block with when clause.

   catch(ExceptionClass ex) when (condition)
  {
  }

using System;
namespace Csharp6_features
{
    class ExceptionFilter
    {
        public static void Main()
        {
            bool debug = true; 
            try
            {
                int n1 = 10, n2 = 0;
                Console.WriteLine(n1 / n2);
            }
            catch (Exception ex) when (ex.InnerException != null)  
            {
                Console.WriteLine(ex.InnerException.Message);
            }
            catch (Exception ex) when  (debug)     
            {
                Console.WriteLine("Debugging : " + ex.Message);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error :  " + ex.Message);
            }
        }
    }
}

The nameof Operator

A new operator nameof is provided to get name of the given variable. It is useful as it avoids hard-coding names in messages.

Consider the following snippet. If we ever have to rename variable amount to salesAmount then second exception message reflects the change whereas first message still refers to amount as it is hard-coded. To change messages along with variable names, always use nameof operator.

using System;

namespace Csharp6_features
{
    class NameOfDemo
    {
        public static void Main()
        {
            int amount = 10;

            // variable name is hard-coded, when amount variable is renamed, message remains same 
            if (amount < 10)
                throw new ArgumentException("Value of amount is invalid"); 
            // When amount variable is renamed, message is automatically updated 
            if (amount > 100)
                throw new ArgumentException("Value of " + nameof(amount) + " is too high!");

            // Same as above, but uses String interpolation 
            if (amount > 50)
                throw new ArgumentException($"Value of {nameof(amount)} is high!");
        }
    }
}

Null conditional operator (? ??)

Whenever we use an object reference that contains null, it throws an exception. So, we have to check whether object reference is not null, before using it. This process is made simple in C# 6.0 as shown in code below.

using System;
using System.Collections.Generic;
namespace Csharp6_features
{
    class NullConditional
    {
        public static void Main()
        {
            String s = null;
            
            // Before C# 6.0, we have to check whether s points to null before using it otherwise it throws exception
            if (s == null)
                Console.WriteLine("null");
            else
                Console.WriteLine(s.ToUpper());

            // C# 6.0 checks whether s is null, if it is null it uses expression given after ?? otherwise it proceeds 

            Console.WriteLine(s?.ToUpper() ?? "Null");
        }
    }
}