Introduction
C# as a language has been there since 12 years. It came along with .NET Framework. And year after year, various versions of C# were released. Let’s have a glance at how C# was available through the years.
Looking at the history, C# really helped us to make our code more readable & easy to achieve our work. But today, in this article, I would like to talk about the upcoming version of C# language, i.e., – C# 6.0. Although you can find a lot of articles related to C# 6.0 features, I will try to explain the problem today and how this new version will help us to solve it efficiently.
C# 6.0 hasn’t added any huge features in this version, but instead they tried to add small features which will help us to keep our code clean.
Features
1) Null Check Operator
Every time we try to access any methods or property of null
object, we usually get a worst & common exception, i.e., – NullReferenceException
.
The above figure explains that I tried to use Split()
to null string
. Now how would you handle this exception?
string strName = null;
string strFirstName = null, strLastName = null;
if (strName != null)
{
string[] splitName = strName.Split();
strFirstName = splitName[0];
strLastName = splitName.Length > 1 ? splitName[1] : null;
}
Console.WriteLine("Splited Data FrstName :{0} LastName :{1}", strFirstName, strLastName);
I tried to first check whether strName
is null
or not, then after splitting checked for array length > 1
or not before assigning LastName
.
But now, in C# 6.0, this job is done in a much simpler way using ?.
operator. This is called as Null
Check Operator or Null
propagation operator.
string strname = null;
string[] splitname1 = strName?.Split();
Console.WriteLine("Splited Data Frstname :{0} Lastname :{1}", splitname1
?[0], splitname1?[1]);
Check the above code snippet.
Null Check operator (?.
) helps:
- Return
null
if the operand is null
. Example - strName?.Split()
- Return
null
if indexed object is null
. Example - splitName?[0]
Isn’t it cool? Now the same is also applicable for nullable type member.
int? result = strName?.Length;
From the above code snippet, if strName
is null
, so Length
property as it is a value type will get converted to nullable automatically.
2) Auto Property Initializer
Usually, when we declare any property, how did we declare it?
Old method:
private readonly Guid _idOld = Guid.NewGuid();
public Guid Id
{
get { return _idOld; }
}
Right, then in C# 4.0, we got automatic implement property, where we stopped writing implementation of getter & setter.
public Customer()
{
NewId = Guid.NewGuid();
}
public Guid NewId
{
get; protected set;
}
Now, you may know that in this way of writing where I want to have only getter accessor for property, we have to have the protected setter accessor as well just to set the initial backing field at constructor. The reason was for mutable datatype
property, we cannot declare variable and leave it without assigning default value, we have to set it, due to which immutable datatype
property was also suffering from this forced set accessor.
In C# 6.0, that problem is permanently removed.
public Guid Id { get; }
public int Number { get; }
Also initialization of property need not be done in constructor, you can do it at the same line of property declaration.
public Guid Id { get; } = Guid.NewGuid();
3) Expression Bodied Function and Members
Whenever we create any method, which consists of single line statement, we normally write it down as shown below:
public string GetName0(string fullname)
{
return fullname;
}
public void Calculate0(int x, int y)
{
Console.WriteLine("Total:" + (x + y));
}
One method GetName0()
return a value & Calculate0()
returns void
.
If you see, it takes around 3 lines of code just for a single one liner statement body.
Now C# 6.0 comes with the expression bodied functions which use a lambda expression to define the body of a method.
public string GetNameN(string fullname) => fullname;
public void CalculateN(int x, int y) => Console.WriteLine("Total:" + (x + y));
4) Using Static
We use various .NET or user defined classes by importing namespaces in our code.
using System.IO;
using System;
namespace cSharp6
{
public class UsingStatic
{
public void ReadFile()
{
string[] filecontent = File.ReadAllLines("c:/test/sample.txt");
Console.WriteLine("Reading file:samle.txt");
Console.WriteLine("--------------------------------------");
foreach (string s in filecontent)
{
Console.WriteLine(s);
}
}
If you see the above sample code, I am trying to read the sample.txt and print it on console.
For reading the file, I made use of System.IO
namespace.
I hope you all know that File
is a static
class that falls under System.IO
namespace.
In C# 6.0, we can keep our code more clean as it now allows you to import Static
classes in using
directive.
using System.Console;
using System.IO.File;
using System;
namespace cSharp6
{
public class UsingStatic
{
public void ReadFile()
{
string[] filecontent = ReadAllLines("c:/test/sample.txt");
WriteLine("Reading file:samle.txt");
WriteLine("--------------------------------------");
foreach (string s in filecontent)
{
WriteLine(s);
}
}
Note: Let's say you have a custom method with name WriteLine()
already in your class. In that case, no ambiguity error will occur and preference will be given to internal
class method and not Static
class method.
5) Dictionary Initializer
When you declare any dictionary, how do we normally create it?
Note: Dictionary
class was brought in C# 3.0.
public Dictionary<string, Customer> clist = new Dictionary<string, Customer>();
The above dictionary
is holding Customer
object.
Same dictionary when created with object initializer then?
public Dictionary<string, Customer> clist = new Dictionary<string, Customer>()
{
{"a", new Customer() { CustomerName = "Ron" }},
{"b", new Customer() { CustomerName = "Robert" }}
};
If you see, it sometimes gets very difficult to manage the braces, we sometimes get confused with the closing curly braces.
So to make our work easier and development faster, C# 6.0 came up with a syntax as shown below:
public Dictionary<string, Customer> clist = new Dictionary<string, Customer>()
{
["a"] = new Customer() { CustomerName = "Ron" },
["b"] = new Customer() { CustomerName = "Robert" }
};
Now, you can set the key of dictionary
by assigning the value. Is it cool?
I really liked this code stuff as many times our dictionary
value could be a complex class.
6) String Interpolation
When we print something, let's say on browser, messagebox, console, etc., we either write:
Console.WriteLine("My fav football player is " + firstName + " " + lastName);
Or we use string.Format()
method with placeholder:
Console.WriteLine(string.Format("My fav football player is {0} {1}", firstName, lastName));
Think of a situation if the string
you are printing is huge with many placeholder’s values, it becomes difficult to manage and count the placeholder values, else it will give an error.
What if C# 6.0 gives you a better way to represent the string
? This is what is called as string
interpolation.
Previous CTP version of VS2015 was having syntax as shown below
Console.WriteLine("My fav football player is \{firstName} \{lastName}");
You can use \{}
character and replace the variables within these curly brackets.
Now in the latest CTP version, i.e., CTP 6, the syntax has been changed a bit. Now they used $ and made it much simpler.
Console.WriteLine($"{firstname} {lastname}");
Now, you don’t need to remember how many placeholders are defined and how many variables are declared. (Note: This situation mainly comes when string
is a huge string
.)
You may be thinking what in case I want {firstname}
as a part of string
and not placeholder. In that case, use \
. It will consider it as escape character. i.e. \{firstname}.
Note: This syntax was already present in Python language, now adopted by Microsoft for C#.
7) Exception Filter
Catching an exception is the most required part in our day to day coding. When we want to handle any exception, we normally use try catch
block.
My condition here is I want to handle only InvalidOperationException
, check what I did in the code below:
public void CalculateO(int x, int y)
{
try
{
int index = 10;
int j = (x*index) / y;
}
catch (Exception e)
{
if (e.Message.Contains("InvalidOperationException"))
Console.WriteLine("Mail error 2:" + e.Message);
throw;
}
}
I added a condition in catch
block for error message containing ‘InvalidOperationException
’.
Now check the same Exception handling provided in C# 6.0.
public void CalculateN(int x, int y)
{
try
{
int index = 10;
int j = (x*index) / y;
}
catch (InvalidOperationException e)if(e.Message.Contains("unknown error"))
{
Console.WriteLine("Mail error 1:" + e.Message);
}
}
The above code snippet shows the catch
along with contextual if
statement.
Reading many articles on C# 6.0 and from audience comments, you may feel both are almost the same and of no use, in fact I may have to write multiple catch
blocks in C# 6.0 syntax if more conditions need to be checked which is very simple in the previous code.
Then, why C# got this code?
An answer is there is a huge fundamental difference between both the code snippets above.
In the 1st way, I am first catching the block and then checking the condition, i.e., – Exception is caught already |
In the 2nd way, I am checking the condition and then moving to catch block, i.e.,- Exception is caught on satisfying the condition |
In the first case, if you want the exception other than your condition, then you will rethrow the exception and your exception will be bubbled up. But at the same time, you will lose your critical information because of crash dumps like from which line the exception was rethrown & what were the values, let's say index was holding as shown in the below figure.
Check what advantage we have in the new syntax. You are getting the unhandled exception there itself.
In the 1st case catch
block, the local variable is not on the top stack frame. This fairly corresponds to what you see in the crash dumps.
Notice in the 2nd case, you can easily investigate the error location and it helps you better to understand it.
8) Async Await with Await in Catch Block
We know that async await
keywords were introduced in C# 5.0. This are mainly meant for asynchronous calls. Let’s consider a sample example wherein I am having a method which is taking time for processing.
public async void AsyncCall()
{
Console.WriteLine("Called..");
Task<string> theTask = ProcessData();
try
{
string result = await theTask;
Console.WriteLine("Result: " + result);
}
catch (Exception ex)
{
Console.WriteLine("Result: " + ex.Message);
}
}
private async Task<string> ProcessData()
{
await Task.Delay(1000);
return "Processed all records";
}
As shown in the code above, ProcessData()
method is processing data for 10 minutes asynchronously, and I get an error, I will catch that Exception
in catch
block.
Imagine that I want to log the exception
in catch
block and that too takes some 20 minutes.
Don’t you think it should also be called using await
keyword for asynchronous call. This was not possible in C# 5.0. There is no reason for it.
But with C# 6.0, using await
in catch
block has become possible. See the updated code below:
public async void AsyncCall()
{
Console.WriteLine("Called..");
Task<string> theTask = ProcessData();
try
{
string result = await theTask;
Console.WriteLine("Result: " + result);
}
catch (Exception ex)
{
Console.WriteLine("Result: " + await LogError(ex));
}
}
private async Task<string> ProcessData()
{
await Task.Delay(1000);
return "Processed all records";
}
public async Task<string> LogError(Exception ee)
{
await Task.Delay(2000);
Console.WriteLine("Logging....");
return ee.Message;
}
Some of the features were decided to be a part of C# 6.0, but later were removed from this version. They are:
- Primary Constructor
- Prams & IEnumerable
- Declaration Expression
- Literals & separators
Conclusion
Here, I end up my features of C# 6.0. Some are really cool and will definitely help us to keep our code clean and easily readable.
Just to make you aware again that C# 6.0 is not yet released. It is still under CTP version of Visual Studio 2015. But soon, it is going to get released and will be available with us.
Please do share your comments, whether good or bad. Your feedback will definitely motivate me to write better.
The Visual Studio 2015 CTP version can be download from the below link: