Getting Started With C# 6.0 New Features

As we know, C# 6.0 was introduced with Visual Studio 2015. There are several features introduced in several versions of C#,  like LINQ was introduced with C# 3.0. Dynamic features were introduced with C# 4.0. Async and Await were introduced with C# 5.0 etc.

In C# 6.0, the most emphasis was given to syntactical improvements rather than new features to add on. These features will help us to write the code faster and in a simple way.

Thus, I am going to explain and after that I hope you will understand about delegate and love to use delegate. You can find this article on my blog site.

Objective

You can download Visual Studio 2015 or if you have Visual Studio 2013, you need to download Roslyn Package from here. Roslyn is the .NET compiler,  which is an open source and integrated with Visual Studio 2015.

Several new syntactical improvements with C# 6.0 were introduced and are as follows:

  1. Using static
  2. Auto property initializers
  3. Index initializers
  4. String interpolation
  5. Expression bodied members
  6. Getter only auto properties
  7. Exception filters
  8. Null conditional operators
  9. Declaration expressions

Using Static 

 

This is a very interesting feature, which makes your coding life easy. Now, you can define the class via using keyword to access the property or the method of the classes. You need to add only static keyword after using and before the namespace of the class.
  1. using static System.Console;  
When we define the System.Console class with static in using section, we can access all the properties and methods of System.Console. Given below is the example where you will see what we did before C# 6.0 and what we can do in C# 6.0.

Before C# 6.0
  1. using System;  
  2. namespace CSharp6FeaturesDemo {  
  3.  class Program {  
  4.   static void Main(string[] args) {  
  5.    Console.WriteLine("This is demo for C# 6.0 New Features");  
  6.   }  
  7.  }  
  8. }  
Before C# 6.0, if we were to use the WriteLine() method, we would use Console.WriteLine(). WriteLine can not be accessed without the reference of the Console class.

In C# 6.0
  1. using static CSharp6FeaturesDemo.MyClass;  
  2. namespace CSharp6FeaturesDemo {  
  3.  class Program {  
  4.   static void Main(string[] args) {  
  5.    WriteLine("This is demo for C# 6.0 New Features");  
  6.    Hello();  
  7.    ReadLine();  
  8.   }  
  9.  }  
  10.  static class MyClass {  
  11.   public static void Hello() {  
  12.    WriteLine("This is static class");  
  13.   }  
  14.  }  
  15. }  
C# 6.0 provides the flexibility to use the class without the reference of the class every time. We only need to define it in using statement and we can access it.

We can also give the references of the other classes to access their members.
  1. Hello();  
In the example given above, we can see Hello(), which is defined in MyClass.
  1. static class MyClass {  
  2.  public static void Hello() {  
  3.   WriteLine("This is static class");  
  4.  }  
  5. }  
Here, we only define the namespace in using statement with static keyword, as shown below:
  1. using static CSharp6FeaturesDemo.MyClass;  


Auto Property Initializer


To access the internal members, we use the properties. Properties have their getter and setter. Before C# 6.0, we could not directly define the value of the property. To do this, we basically used the local member variables but C# 6.0 provides the flexibility to initialize the value.

With C# 6.0, we can directly assign the value of the property at the time of defining the new property.

Before C# 6.0

Earlier, we generally used constructor to initialize the value of the Property. See the following example, as you can see that we have created multiple properties and to initialize the value, constructor will help.
  1. using System;  
  2. using static System.Console;  
  3. namespace CSharp6FeaturesDemo {  
  4.  public class Program {  
  5.   static void Main(string[] args) {  
  6.    Employee emp = new Employee();  
  7.    Console.WriteLine("Employee Id is " + emp.EmployeeId);  
  8.    Console.WriteLine("Employee Full Name is " + emp.FullName);  
  9.    Console.ReadLine();  
  10.   }  
  11.  }  
  12.  public class Employee {  
  13.   public Guid EmployeeId {  
  14.    get;  
  15.    set;  
  16.   }  
  17.   public string FirstName {  
  18.    get;  
  19.    set;  
  20.   }  
  21.   public string LastName {  
  22.    get;  
  23.    set;  
  24.   }  
  25.   
  26.   public string FullName {  
  27.    get;  
  28.    set;  
  29.   }  
  30.   public Employee() {  
  31.    EmployeeId = Guid.NewGuid();  
  32.    FirstName = "Mukesh";  
  33.    LastName = "Kumar";  
  34.    FullName = string.Format("{0} {1}", FirstName, LastName);  
  35.   }  
  36.  }  
  37. }  
In C# 6.0

C# 6.0 is very smooth and we don't need to worry about how and where we will initialize the value of the property. You can directly assign the value of the property after = sign. It will not give you any type of exception and run smoothly. In the example given below, we can see that EmployeeId is generating new GUID. It is clearly visible that FirstName and LastName are initialized with their values.
  1. using System;  
  2. using static System.Console;  
  3. namespace CSharp6FeaturesDemo {  
  4.  public class Program {  
  5.   static void Main(string[] args) {  
  6.    Employee emp = new Employee();  
  7.    WriteLine("Employee Id is " + emp.EmployeeId);  
  8.    WriteLine("Employee Full Name is " + emp.FullName);  
  9.    ReadLine();  
  10.   }  
  11.  }  
  12.  public class Employee {  
  13.   public Guid EmployeeId {  
  14.    get;  
  15.    set;  
  16.   } = Guid.NewGuid();  
  17.   public string FirstName {  
  18.    get;  
  19.    set;  
  20.   } = "Mukesh";  
  21.   public string LastName {  
  22.    get;  
  23.    set;  
  24.   } = "Kumar";  
  25.   
  26.   public string FullName {  
  27.    get {  
  28.     return string.Format("{0} {1}", FirstName, LastName);  
  29.    }  
  30.   }  
  31.  }  
  32. }  


Index Initializer


C# 6.0 provides a new way to initialize the collection. You can create the index based collections like dictionaries, hashtables etc. As we know, the dictionary is the key-value pair and we need to assign the values for their corresponding keys. We have a different way to create the key/value pair prior to C# 6.0. How we used the key/value pair for a dictionary object in C# prior to C# 6.0 is displayed, with the help of the following example-

Before C# 6.0
  1. using System;  
  2. using System.Collections.Generic;  
  3. namespace CSharp6FeaturesDemo {  
  4.  public class Program {  
  5.   static void Main(string[] args) {  
  6.    Dictionary < intstring > myDictionary = new Dictionary < intstring > () {  
  7.     {  
  8.      1,  
  9.      "Mukesh Kumar"  
  10.     }, {  
  11.      2,  
  12.      "Rahul Rathor"  
  13.     }, {  
  14.      3,  
  15.      "Yaduveer Saini"  
  16.     }, {  
  17.      4,  
  18.      "Banke Chamber"  
  19.     }  
  20.    };  
  21.   
  22.    foreach(var item in myDictionary) {  
  23.     Console.WriteLine("The " + item.Key + " Number Employee is " + item.Value + "\n");  
  24.    }  
  25.    Console.ReadLine();  
  26.   }  
  27.  }  
  28. }  
In C# 6.0

With C# 6.0, we logically define that the value for an index 1 is "Mukesh Kumar" and so on. You can see the following example which clears your all doubts:
  1. using System;  
  2. using System.Collections.Generic;  
  3. using static System.Console;  
  4. namespace CSharp6FeaturesDemo {  
  5.  public class Program {  
  6.   static void Main(string[] args) {  
  7.    Dictionary < intstring > myDictionary = new Dictionary < intstring > () {  
  8.     [1] = "Mukesh Kumar", [2] = "Rahul Rathor", [3] = "Yaduveer Saini", [4] = "Banke Chamber"  
  9.    };  
  10.   
  11.    foreach(var item in myDictionary) {  
  12.     WriteLine("The " + item.Key + " Number Employee is " + item.Value + "\n");  
  13.    }  
  14.    ReadLine();  
  15.   }  
  16.  }  
  17. }  


String Interpolation

For concatenation, we generally use String.Format, where we pass the array of the index and then pass the parameters value for it. It is very confusing when you are working with the multiple members. C# 6.0 has introduced a very great feature, where you don't need to pass the array index, but you can directly pass your variable. Make sure to use the $ sign before starting. Following is the simple example of getting the full name to use the first name and last name. Here, we are using the string.Format and afterwards, we need to specify the index array for the parameters value.

Before C# 6.0
  1. using System;  
  2. using System.Collections.Generic;  
  3.   
  4. namespace CSharp6FeaturesDemo {  
  5.  public class Program {  
  6.   static void Main(string[] args) {  
  7.    string firstName = "Mukesh";  
  8.    string lastName = "Kumar";  
  9.   
  10.    Console.WriteLine("The Full Name of Employee " + string.Format("{0} {1}", firstName, lastName));  
  11.    Console.ReadLine();  
  12.   }  
  13.  }  
  14. }  
In C# 6.0
  1. using System;  
  2. using System.Collections.Generic;  
  3. using static System.Console;  
  4. namespace CSharp6FeaturesDemo {  
  5.  public class Program {  
  6.   static void Main(string[] args) {  
  7.    string firstName = "Mukesh";  
  8.    string lastName = "Kumar";  
  9.   
  10.    WriteLine($ "The Full Name of Employee {firstName} {lastName}");  
  11.    ReadLine();  
  12.   }  
  13.  }  
  14. }  


Expression Bodied Members

Lambda expressions are very useful when you are working with LINQ query. In C# 6.0, you can use lambda expressions with the properties and functions to increase your productivity and write clean code.

Using lambda expressions, you can define the method in one line [Use only for simple and short logical methods or properties]. I believe, when you are working with the large Application and you need to get a single value, based on the condition we can use the expression bodied members. We can directly create a function and also get the output, based on their parameter values.

Before C# 6.0

Earlier, we generally created a separate method to complete any simple task. It might be one line or more than one line. It was very complex and time consuming. See the following example, where two methods GetFullName and AddTwoNumber are doing the simple task like concatenating two strings and adding the two numbers. To complete this task, we need to write two separate methods. 

  1. using System;  
  2. using System.Collections.Generic;  
  3.   
  4. namespace CSharp6FeaturesDemo {  
  5.  public class Program {  
  6.   public static string GetFullName(string firstName, string lastName) {  
  7.    return string.Format("{0} {1}", firstName, lastName);  
  8.   }  
  9.   public static int AddTwoNumber(int firstNumber, int secondNumber) {  
  10.    return firstNumber + secondNumber;  
  11.   }  
  12.   static void Main(string[] args) {  
  13.    string firstName = "Mukesh";  
  14.    string lastName = "Kumar";  
  15.    int firstNumber = 10;  
  16.    int secondNumber = 20;  
  17.   
  18.    Console.WriteLine(GetFullName(firstName, lastName));  
  19.    Console.WriteLine(AddTwoNumber(firstNumber, secondNumber));  
  20.    Console.ReadLine();  
  21.   }  
  22.  }  
  23. }  
In C# 6.0

C# 6.0 is not required to create separate methods for only a single task. It can be defined and completed at that time, when it is defining.
  1. using System;  
  2. using System.Collections.Generic;  
  3. using static System.Console;  
  4. namespace CSharp6FeaturesDemo {  
  5.  public class Program {  
  6.   public static string GetFullName(string firstName, string lastName) => firstName + " " + lastName;  
  7.   public static int AddTwoNumber(int firstNumber, int secondNumber) => firstNumber + secondNumber;  
  8.   static void Main(string[] args) {  
  9.    string firstName = "Mukesh";  
  10.    string lastName = "Kumar";  
  11.    int firstNumber = 10;  
  12.    int secondNumber = 20;  
  13.   
  14.    WriteLine(GetFullName(firstName, lastName));  
  15.    WriteLine(AddTwoNumber(firstNumber, secondNumber));  
  16.    ReadLine();  
  17.   }  
  18.  }  
  19. }  


Getter Only Auto Properties


When you are working with the properties, you need to define the getter and setter both; But in C# 6.0 you can define only the getter for properties. Before C# 6.0 you need to define them both when going to create properties. Sometimes, it is not required to create the setter but we need to define it. But there is not any restriction to make such type of coding with C# 6.0. You can only define the getter for the properties and make it readonly.

See the following example where FirstName and LastName have their getter with their values.

In C# 6.0
  1. using System;  
  2. using System.Collections.Generic;  
  3.   
  4. namespace CSharp6FeaturesDemo {  
  5.  public class Program {  
  6.   string FirstName {  
  7.    get;  
  8.   } = "Mukesh";  
  9.   string LastName {  
  10.    get;  
  11.   } = "Kumar";  
  12.   
  13.   public string FullName = string.Empty;  
  14.   public Program() {  
  15.    FullName = FirstName + " " + LastName;  
  16.   }  
  17.   static void Main(string[] args) {  
  18.    Program prog = new Program();  
  19.    Console.WriteLine("The Full Name is " + prog.FullName);  
  20.    Console.ReadLine();  
  21.   }  
  22.  }  
  23. }  


Exception Filters


It is available with VB but when the new compiler "Roslyn" is introduced, this feature is added with it. Exception filter is used to specify the catch block on the basis of some conditional arguments. Generally, we define only one catch block and inside it, we will make different conditions for throwing the different types of exceptions.

In C# 6.0, you can check the message and show the exception message as per your conditions.

Before C# 6.0

  1. using System;  
  2. using System.Collections.Generic;  
  3.   
  4. namespace CSharp6FeaturesDemo {  
  5.  public class Program {  
  6.   static void Main(string[] args) {  
  7.    int errorCode = 404;  
  8.    try {  
  9.     throw new Exception(errorCode.ToString());  
  10.    } catch (Exception ex) {  
  11.     if (ex.Message.Equals("404"))  
  12.      Console.WriteLine("This is Http Error");  
  13.     else if (ex.Message.Equals("401"))  
  14.      Console.WriteLine("This is Unathorized Error");  
  15.     else  
  16.      Console.WriteLine("This is some different exception");  
  17.   
  18.     Console.ReadLine();  
  19.   
  20.    }  
  21.   
  22.   }  
  23.  }  
  24. }  
In C# 6.0

With C# 6.0, we can check the exception message and on the basis of the exception, it can be defined in the catch block. It can be used with multiple catch blocks and every catch block will be checked with its own conditional message.
  1. using System;  
  2. using System.Collections.Generic;  
  3. using static System.Console;  
  4. namespace CSharp6FeaturesDemo {  
  5.  public class Program {  
  6.   static void Main(string[] args) {  
  7.    int errorCode = 404;  
  8.    try {  
  9.     throw new Exception(errorCode.ToString());  
  10.    } catch (Exception ex) when(ex.Message.Equals("404")) {  
  11.     WriteLine("This is Http Error");  
  12.    } catch (Exception ex) when(ex.Message.Equals("401")) {  
  13.     WriteLine("This is Unathorized Error");  
  14.    } catch (Exception ex) when(ex.Message.Equals("403")) {  
  15.     WriteLine("Forbidden");  
  16.    }  
  17.    ReadLine();  
  18.   }  
  19.   
  20.  }  
  21. }  


You can see that on the basis of the error code, the catch block is going to execute.

Null Conditional Operators

At the time of coding, we generally check the null value to make some conditions. We check if the object is null or not and try to prevent the NullReferenceException. To do this, we need to write some extra code, which also makes the code lengthy.

With C# 6.0, you don't need to write some extra code and you can use null conditional operator, which is nothing but only a question mark [?] sign.

Before C# 6.0

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4.   
  5. namespace CSharp6FeaturesDemo {  
  6.  public class Program {  
  7.   
  8.   static void Main(string[] args) {  
  9.    List < Employee > employees = new List < Employee > ();  
  10.    Program prog = new Program();  
  11.    if (employees.FirstOrDefault() != null) {  
  12.     //This code will not hit because of employees is null;  
  13.     Console.WriteLine(employees.First().Name);  
  14.    } else {  
  15.     Employee emp = new Employee();  
  16.     emp.EmployeeId = 10;  
  17.     emp.Name = "Mukesh Kumar";  
  18.     emp.Address = "New Delhi";  
  19.     employees.Add(emp);  
  20.     Console.WriteLine(employees.First().Name);  
  21.    }  
  22.    Console.ReadLine();  
  23.   }  
  24.  }  
  25.  public class Employee {  
  26.   public int EmployeeId {  
  27.    get;  
  28.    set;  
  29.   }  
  30.   public string Name {  
  31.    get;  
  32.    set;  
  33.   }  
  34.   public string Address {  
  35.    get;  
  36.    set;  
  37.   }  
  38.   
  39.  }  
  40. }  
In C# 6.0
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using static System.Console;  
  5. using static System.Console;  
  6. namespace CSharp6FeaturesDemo {  
  7.  public class Program {  
  8.   
  9.   static void Main(string[] args) {  
  10.    List < Employee > employees = new List < Employee > ();  
  11.    Program prog = new Program();  
  12.   
  13.    //No need to check null in if condition  
  14.    //null operator ? will check and return null if value is not there  
  15.    WriteLine(employees.FirstOrDefault() ? .Name);  
  16.   
  17.    //set the default value if value is null  
  18.    WriteLine(employees.FirstOrDefault() ? .Name ? ? "My Value");  
  19.   
  20.    ReadLine();  
  21.   }  
  22.  }  
  23.  public class Employee {  
  24.   public int EmployeeId {  
  25.    get;  
  26.    set;  
  27.   }  
  28.   public string Name {  
  29.    get;  
  30.    set;  
  31.   }  
  32.   public string Address {  
  33.    get;  
  34.    set;  
  35.   }  
  36.   
  37.  }  
  38. }  


First value is not going to print anything and is not throwing any error also. It is because the ? sign is included with the statement, which handles the null exception. For the second statement, the default value "My Value" is going to print because the value is null.

Declaration Expressions


Using this feature, we don't need to declare the local variable globally. We can generally create it inside the expression. The scope of the variable will be inside the loop, where it is defined.

Before C# 6.0
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4.   
  5. namespace CSharp6FeaturesDemo {  
  6.  public class Program {  
  7.   static void Main(string[] args) {  
  8.    int myValue = 10;  
  9.    if (int.TryParse("20"out myValue)) {  
  10.     Console.WriteLine(myValue);  
  11.     Console.ReadLine();  
  12.    }  
  13.   }  
  14.  }  
  15. }  
In C# 6.0
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using static System.Console;  
  5. namespace CSharp6FeaturesDemo {  
  6.  public class Program {  
  7.   static void Main(string[] args) {  
  8.    if (int.TryParse("20"out  
  9.      var result)) {  
  10.     return result;  
  11.    }  
  12.    return 0; // result is out of scope  
  13.   
  14.    // A new feature in C# 6.0 allows to declare variable inside TryParse method.  
  15.    //Declaration expressions was cut from C# 6.0 and wasn't shipped in the final release.   
  16.    //You currently can't do that. There is a proposal for it on GitHub for C# 7.  
  17.   }  
  18.  }  
Conclusion

Finally, we have learned about the new features of C# 6.0. It makes our coding life easy because it provides a simple way to do a complex thing. We need to make a habit to adopt it in our daily coding. I hope this will help you to make your code better and clean.

At last, thanks for reading this article. Hope, you enjoyed it. Please give your suggestion and feedback to improve this article through the comments.