Get a quick glance at what's new in C# 6.0. Here are the features with easy to understand examples.
static types as using
So, we are all quite familiar with this notion of accessing static class members using the qualification first. It is not required now. Importing static using can save the day. For example, before C# 6.0, we had to access ReadKey(), WriteLine() methods of the Console class by explicitly defining the static class qualifier.
- using System;
-
- namespace NewInCSharp
- {
- class Program
- {
- static void Main(string[] args)
- {
- MySelf.WhoAmI();
- Console.ReadKey();
- }
- }
-
- static class MySelf
- {
- public static void WhoAmI()
- {
- Console.WriteLine("I'm Fizz!");
- }
- }
- }
In C# 6.0, we can get rid of the qualifiers just by importing the static types in the namespace like the following code snippet:
- using static System.Console;
- using static NewInCSharp.MySelf;
-
- namespace NewInCSharp
- {
- class Program
- {
- static void Main(string[] args)
- {
- WhoAmI();
- ReadKey();
- }
- }
-
- static class MySelf
- {
- public static void WhoAmI()
- {
- WriteLine("I'm Fizz!");
- }
- }
- }
String interpolation
You can now forget using placeholders in strings to replace them with real values. C# 6 has a new feature called string interpolation using which you can now directly write your arguments instead of referring them with placeholders inside a string. You can also do whatever you would have done previously with
String.Format() function.
Before C# 6.0 - using System;
- using System.Collections.Generic;
- using static System.Console;
-
- namespace NewInCSharp
- {
- class Program
- {
- private static void Main(string[] args)
- {
- string name = "Murphy Cooper";
- string planet = "Cooper Station";
-
- WriteLine("{0} is actually named after {1}", planet, name);
-
- ReadLine();
- }
- }
- }
After C# 6.0 - using System;
- using System.Collections.Generic;
- using static System.Console;
-
- namespace NewInCSharp
- {
- class Program
- {
- private static void Main(string[] args)
- {
- string name = "Murphy Cooper";
- string planet = "Cooper Station";
-
-
- WriteLine($"{planet} is actually named after {name}");
-
- ReadLine();
- }
- }
- }
Again these are some string formatting examples which I missed in the video:
- string name = "Sammy Jenkins";
- double salary = 1000;
-
- WriteLine($"{name}'s monthly salary is {salary:C2}");
- WriteLine($"Man! This {name} is kind of a {(salary >= 1000 ? "rich guy" : "poor guy")}");
-
-
-
-
-
Dictionary Initializers
C# 6.0 changed the way you can initialize
Dictionary. Previously on C# 5 you would have to initialize the Dictionary with this type of syntax, {"Key", "Value"}. Now in C# 6.0 you can just place the key between two curly brackets ["
Key"] and then set the value of the key [
"Key"] = "value"; , just like you set value for other types of variable. This new syntax is more friendlier than before.
Before C# 6 - using System.Collections.Generic;
- using static System.Console;
-
- namespace NewInCSharp
- {
- class Program
- {
- private static void Main(string[] args)
- {
- Dictionary alien = new Dictionary()
- {
- {"Name", "Fizzy"},
- {"Planet", "Kepler-452b"}
- };
-
- foreach (KeyValuePair keyValuePair in alien)
- {
- WriteLine(keyValuePair.Key + ": " + keyValuePair.Value + "\n");
- }
-
- ReadLine();
- }
- }
- }
In C# 6.0 - using System.Collections.Generic;
- using static System.Console;
-
- namespace NewInCSharp
- {
- class Program
- {
- private static void Main(string[] args)
- {
-
- Dictionary alien = new Dictionary()
- {
- ["Name"] = "Fizzy",
- ["Planet"] = "Kepler-452b"
-
- };
-
- foreach (KeyValuePair keyValuePair in alien)
- {
- WriteLine(keyValuePair.Key + ": " + keyValuePair.Value + "\n");
- }
-
- ReadLine();
- }
- }
- }
Auto-Property Initializers
C# 6.0 came with a new concept of initializing class properties inline rather than initializing them within the type's constructor. Another handy technique is, if you want to make the setter of a property private to block users from setting value in the property by an instance, you can just declare a getter only property. For example,
Before C# 6 - using static System.Console;
-
- namespace NewInCSharp
- {
- class Program
- {
- static void Main(string[] args)
- {
- Employee employee = new Employee();
-
- WriteLine("Name: " + employee.Name + "\nSalary: " + employee.Salary);
-
- ReadKey();
- }
- public class Employee
- {
- public string Name { get; set; }
- public decimal Salary { get; set; }
- public Employee()
- {
-
- Name = "Sammy Jenkins";
- Salary = 10000;
- }
- }
- }
- }
In C# 6.0 - using static System.Console;
-
- namespace NewInCSharp
- {
- class Program
- {
- static void Main(string[] args)
- {
- Employee employee = new Employee();
-
- WriteLine("Name: " + employee.Name + "\nSalary: " + employee.Salary);
-
- ReadKey();
- }
- public class Employee
- {
-
- public string Name { get; } = "Sammy Jenkins"
-
-
- public decimal Salary { get; set; } = 10000;
- }
- }
- }
nameof expression
Next is the
nameof expression. In enterprise level applications, lines of code run like a mad horse. So there is no means of avoiding exception handling where it is necessary. Showing a specific type name with an error message can be a quick way to find the code block where the exception just occurred. But we should also consider refactoring issues. We cannot just simply append a hard coded type name string with an error message and show it to the user because the type name can be changed anytime while refactoring but hard coded string won't change accordingly. So C# 6.0 introduced this concept of
nameof expression. A simple example would be like the following:
Before C# 6 - using System;
- using static System.Console;
-
- namespace NewInCSharp
- {
- class Program
- {
- private static void Main(string[] args)
- {
- try
- {
- CallSomething();
- }
- catch (Exception exception)
- {
- WriteLine(exception.Message);
- }
-
- ReadKey();
- }
-
- private static void CallSomething()
- {
- int? x = null;
-
- if (x == null)
- {
- throw new Exception("x is null");
-
-
- }
- }
- }
- }
- class Program
- {
- private static void Main(string[] args)
- {
- try
- {
- CallSomething();
- }
- catch (Exception exception)
- {
- WriteLine(exception.Message);
- }
-
- ReadKey();
- }
-
- private static void CallSomething()
- {
- int? x = null;
-
- if (x == null)
- {
-
-
- throw new Exception("x is null");
- }
- }
- }
In C# 6.0 - using System;
- using static System.Console;
-
- namespace NewInCSharp
- {
- class Program
- {
- private static void Main(string[] args)
- {
- try
- {
- CallSomething();
- }
- catch (Exception exception)
- {
- WriteLine(exception.Message);
- }
-
- ReadKey();
- }
-
- private static void CallSomething()
- {
- int? number = null;
-
- if (number == null)
- {
- throw new Exception(nameof(number) + " is null");
- }
- }
- }
- }
await in catch/finally block
I think many of you were waiting for this feature in C# where you can write asynchronous codes inside catch and finally block. Well now you can do that.
- using System;
- using System.Net.Http;
- using System.Threading.Tasks;
- using static System.Console;
-
- namespace NewInCSharp
- {
- class Program
- {
- private static void Main(string[] args)
- {
- Task.Factory.StartNew(() => GetWeather());
- ReadKey();
- }
-
- private async static Task GetWeather()
- {
- HttpClient client = new HttpClient();
- try
- {
- var result = await client.GetStringAsync("http://api.openweathermap.org/data/2.5/weather?q=Dhaka,bd");
- WriteLine(result);
- }
- catch (Exception exception)
- {
- try
- {
-
-
- var result = await client.GetStringAsync("http://api.openweathermap.org/data/2.5/weather?q=NewYork,us");
-
- WriteLine(result);
- }
- catch (Exception)
- {
- throw;
- }
- }
- }
- }
- }
null conditional operator & null propagation
Again we have this new notion of null conditional operator where you can remove declaring a conditional branch to check to see if an instance of an object is null or not with this new ?. ?? null conditional operator syntax. The ?. is used to check if a instance is null or not, if its not null then execute the code after ?. but if it is not then execute code after ??. Check out the example below,
Before C# 6.0 - using System;
- using static System.Console;
-
- namespace NewInCSharp
- {
- class Program
- {
- private static void Main(string[] args)
- {
- SuperHero hero = new SuperHero();
- if (hero.SuperPower == String.Empty)
- {
- hero = null;
- }
-
-
- WriteLine(hero != null ? hero.SuperPower : "You aint a super hero.");
-
- ReadLine();
- }
- }
-
- public class SuperHero
- {
- public string SuperPower { get; set; } = "";
- }
- }
In C# 6.0 - using System;
- using static System.Console;
-
- namespace NewInCSharp
- {
- class Program
- {
- private static void Main(string[] args)
- {
- SuperHero hero = new SuperHero();
- if (hero.SuperPower == String.Empty)
- {
- hero = null;
- }
-
-
- WriteLine(hero?.SuperPower ?? "You aint a super hero.");
-
- ReadLine();
- }
- }
-
- public class SuperHero
- {
- public string SuperPower { get; set; } = "";
- }
- }
Again checking a list instance if it is null or not and then accessing its index is also somewhat similar.
- using System;
- using System.Collections.Generic;
- using static System.Console;
-
- namespace NewInCSharp
- {
- class Program
- {
- private static void Main(string[] args)
- {
- List superHeroes = null;
- SuperHero hero = new SuperHero();
-
- if (hero.SuperPower != String.Empty)
- {
- superHeroes = new List();
- superHeroes.Add(hero);
- }
-
- WriteLine(superHeroes?[0].SuperPower ?? "There is no such thing as super heros.");
- ReadLine();
- }
- }
-
- public class SuperHero
- {
- public string SuperPower { get; set; } = "";
- }
- }
What if you want to invoke an event/delegate after checking if the handler function is null or not? Well the null checking syntax would be like in the example below. It is also known as null propagation.
Before C# 6.0 - using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using static System.Console;
-
- namespace NewInCSharp
- {
- class Program
- {
- private static void Main(string[] args)
- {
- Movie movie = new Movie();
- movie.Title = "The Shawshank Redemption";
- movie.Rating = 9.3;
- WriteLine("Title: "+ movie.Title + "\nRating: " + movie.Rating);
- ReadLine();
- }
- }
-
- public class Movie : INotifyPropertyChanged
- {
- public string Title { get; set; }
- public double Rating { get; set; }
- public event PropertyChangedEventHandler PropertyChanged;
-
- protected void OnPropertyChanged(string name)
- {
- PropertyChangedEventHandler handler = PropertyChanged;
-
-
- if (handler != null)
- {
- handler(this, new PropertyChangedEventArgs(name));
- }
- }
- }
- }
In C# 6.0 - using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using static System.Console;
-
- namespace NewInCSharp
- {
- class Program
- {
- private static void Main(string[] args)
- {
- Movie movie = new Movie();
- movie.Title = "The Shawshank Redemption";
- movie.Rating = 9.3;
- WriteLine("Title: "+ movie.Title + "\nRating: " + movie.Rating);
- ReadLine();
- }
- }
-
- public class Movie : INotifyPropertyChanged
- {
- public string Title { get; set; }
- public double Rating { get; set; }
- public event PropertyChangedEventHandler PropertyChanged;
-
- protected void OnPropertyChanged(string name)
- {
- PropertyChangedEventHandler handler = PropertyChanged;
-
-
- handler?.Invoke(this, new PropertyChangedEventArgs(name));
- }
- }
- }
Expression bodied function & property
You can now write functions and computed properties like lamda expressions to save extra headache of defining function and property statement block. Just use the lambda operator
=> and then start writing your code that goes into your function/property body. Here is a simple example,
- using static System.Console;
-
- namespace NewInCSharp
- {
- internal class Program
- {
- private static void Main(string[] args)
- {
- double x = 1.618;
- double y = 3.142;
-
- WriteLine(AddNumbers(x, y));
- ReadLine();
- }
-
-
- private static double AddNumbers(double x, double y) => x + y;
- }
- }
For expression bodied property:
- using static System.Console;
-
- namespace NewInCSharp
- {
- class Program
- {
- private static void Main(string[] args)
- {
- Person person = new Person();
- WriteLine("I'm " + person.FullName);
- ReadLine();
- }
-
- public class Person
- {
- public string FirstName { get; } = "Fiyaz";
- public string LastName { get; } = "Hasan";
-
-
- public string FullName => FirstName + " " + LastName;
- }
- }
- }
static using with Extension methods
This one is kind of related to the first one. Those of you who are wondering that if I import static types in my namespace how would I deal with the extension methods. Well extension methods are also static methods. It is true if you import a static type which have a extension method, you just cannot access the extension methods. It says, "The name [name of the function] does not exist in the current context". So what to do then? Well you can explicitly write the static type name like in C# 5 or previous versions or you can simply execute the function on one of its accepted types. Let me make it clear by an example,
Before C# 6 - using System;
-
- namespace NewInCSharp
- {
- class Program
- {
- private static void Main(string[] args)
- {
- Shape shape = new Shape();
- ShapeUtility.GenerateRandomSides(shape);
- Console.WriteLine(ShapeUtility.IsPolygon(shape));
- Console.ReadLine();
- }
- }
- public class Shape
- {
- public int Sides { get; set; }
- }
-
- public static class ShapeUtility
- {
- public static bool IsPolygon(this Shape shape)
- {
- return shape.Sides >= 3;
- }
-
- public static void GenerateRandomSides(Shape shape)
- {
- Random random = new Random();
- shape.Sides = random.Next(1, 6);
- }
- }
- }
In C# 6.0 importing static types and accessing extension methods of them like the code above will give you a error. The following code will generate the "The name 'IsPolygon' does not exist in the current context".
- using System;
- using static System.Console;
- using static NewInCSharp.ShapeUtility;
-
- namespace NewInCSharp
- {
- class Program
- {
- private static void Main(string[] args)
- {
- Shape shape = new Shape();
- GenerateRandomSides(shape);
- WriteLine(IsPolygon(shape));
- ReadLine();
- }
- }
- public class Shape
- {
- public int Sides { get; set; }
- }
-
- public static class ShapeUtility
- {
- public static bool IsPolygon(this Shape shape)
- {
- return shape.Sides >= 3;
- }
-
- public static void GenerateRandomSides(Shape shape)
- {
- Random random = new Random();
- shape.Sides = random.Next(1, 6);
- }
- }
- }
So to get over this issue you can simply modify you code like this,
- using System;
- using static System.Console;
- using static NewInCSharp.ShapeUtility;
-
- namespace NewInCSharp
- {
- class Program
- {
- private static void Main(string[] args)
- {
- Shape shape = new Shape();
- GenerateRandomSides(shape);
-
-
-
- WriteLine(shape.IsPolygon());
- ReadLine();
- }
- }
- public class Shape
- {
- public int Sides { get; set; }
- }
-
- public static class ShapeUtility
- {
- public static bool IsPolygon(this Shape shape)
- {
- return shape.Sides >= 3;
- }
-
- public static void GenerateRandomSides(Shape shape)
- {
- Random random = new Random();
- shape.Sides = random.Next(1, 6);
- }
- }
- }
There is one more feature that is 'Exception Filtering'. I wrote a separate post for that. Check it out here,
Exception filtering in C# 6.0. So, these are some new feature of C# 6.0 explained with some simple example. To know more on what's coming next, be sure to keep your eye on this git repo documentation,
New Language Features in C# 6
Hope you enjoyed the post. Share it if you like.