Wednesday, September 30, 2015

15 Cool New Features in C# 6.0

List of New Features in C# 6.0

We can discuss about each of the new features, but first, below is a list of few features in C# 6.0:
  1. Auto Property Initializer
  2. Primary Consturctors
  3. Dictionary Initializer
  4. Declaration Expressions
  5. Static Using
  6. await inside catch block
  7. Exception Filters
  8. Conditional Access Operator to check NULL Values

1. Auto Property Initialzier

Before

The only way to initialize an Auto Property is to implement an explicit constructor and set property values inside it.
public class AutoPropertyBeforeCsharp6
{
    private string _postTitle = string.Empty;
    public AutoPropertyBeforeCsharp6()
    {
        //assign initial values
        PostID = 1;
        PostName = "Post 1";
    }

    public long PostID { get; set; }

    public string PostName { get; set; }

    public string PostTitle
    {
        get { return _postTitle; }
        protected set
        {
            _postTitle = value;
        }
    }
}

After

In C# 6, auto implemented property with initial value can be initialized without having to write the constructor. We can simplify the above example to the following:
public class AutoPropertyInCsharp6
{
    public long PostID { get;  } = 1;

    public string PostName { get; } = "Post 1";

    public string PostTitle { get; protected set; } = string.Empty;
}

2. Primary Constructors

We mainly use constructor to initialize the values inside it. (Accept parameter values and assign those parameters to instance properties).

Before

public class PrimaryConstructorsBeforeCSharp6
{
    public PrimaryConstructorsBeforeCSharp6(long postId, string postName, string postTitle)
    {
        PostID = postId;
        PostName = postName;
        PostTitle = postTitle; 
    }

    public long PostID { get; set; }
    public string PostName { get; set; }
    public string PostTitle { get; set; }
}

After

public class PrimaryConstructorsInCSharp6(long postId, string postName, string postTitle)
{        
    public long PostID { get;  } = postId;
    public string PostName { get; } = postName;
    public string PostTitle { get;  } = postTitle;
}
In C# 6, primary constructor gives us a shortcut syntax for defining constructor with parameters. Only one primary constructor per class is allowed.
If you look closely at the above example, we moved the parameters initialization beside the class name.
You may get the following error “Feature ‘primary constructor’ is only available in ‘experimental’ language version.” To solve this, we need to edit the SolutionName.csproj file to get rid of this error. What you have to do is we need to add additional setting after WarningTag.
<LangVersion>experimental</LangVersion>
Feature 'primary constructor' is only available in 'experimental' language version
Feature ‘primary constructor’ is only available in ‘experimental’ language version

3. Dictionary Initializer

Before

The old way of writing a dictionary initializer is as follows:
public class DictionaryInitializerBeforeCSharp6
{
    public Dictionary<string, string> _users = new Dictionary<string, string>()
    {
        {"users", "Venkat Baggu Blog" },
        {"Features", "Whats new in C# 6" }
    };
}

After

We can define dictionary initializer like an array using square brackets.
public class DictionaryInitializerInCSharp6
{
    public Dictionary<string, string> _users { get; } = new Dictionary<string, string>()
    {
        ["users"]  = "Venkat Baggu Blog",
        ["Features"] =  "Whats new in C# 6" 
    };
}

4. Declaration Expressions

Before

public class DeclarationExpressionsBeforeCShapr6()
{
    public static int CheckUserExist(string userId)
    {
        //Example 1
        int id;
        if (!int.TryParse(userId, out id))
        {
            return id;
        }
        return id;
    }

    public static string GetUserRole(long userId)
    {
        ////Example 2
        var user = _userRepository.Users.FindById(x => x.UserID == userId);
        if (user!=null)
        {
            // work with address ...

            return user.City;
        }
    }
}

After

In C# 6, you can declare an local variable in the middle of the expression. With declaration expressions, we can also declare variables inside if statements and various loop statements.
public class DeclarationExpressionsInCShapr6()
{
    public static int CheckUserExist(string userId)
    {
        if (!int.TryParse(userId, out var id))
        {
            return id;
        }
        return 0;
    }

    public static string GetUserRole(long userId)
    {
        ////Example 2
        if ((var user = _userRepository.Users.FindById(x => x.UserID == userId) != null)
        {
            // work with address ...

            return user.City;
        }
    }
}

5. Using Statics

Before

To you static members, you don’t need an instance of object to invoke a method. You use syntax as follows:
TypeName.MethodName
public class StaticUsingBeforeCSharp6
{
    public void TestMethod()
    {
        Console.WriteLine("Static Using Before C# 6");
    }
}

After

In C# 6, you have the ability to use the Static Members without using the type name. You can import thestatic classes in the namespaces.
If you look at the below example, we moved the Static Console class to the namespace:
using System.Console;
namespace newfeatureincsharp6
{
    public class StaticUsingInCSharp6
    {
        public void TestMethod()
        {
            WriteLine("Static Using Before C# 6");
        }
    }
}

6. await Inside catch Block

Before C# 6, await keyword is not available inside the catch and finally blocks. In C# 6, we can finally use theawait keyword inside catch and finally blocks.
try 
{         
 //Do something
}
catch (Exception)
{
 await Logger.Error("exception logging")
}

7. Exception Filters

Exception filters allow you a feature to check an if condition before the catch block executes.
Consider an example that an exception occurred now we want to check if the InnerException null, then it will execute catch block.
//Example 1
try
{
    //Some code
}
catch (Exception ex) if (ex.InnerException == null)
{
    //Do work

}

//Before C# 6 we write the above code as follows

//Example 1
try
{
    //Some code
}
catch (Exception ex) 
{
    if(ex.InnerException != null)
    {
        //Do work;
    }
}

8. Conditional Access Operator to Check NULL Values?

Consider an example that we want to retrieve a UserRanking based on the UserID only if UserID is not null.

Before

var userRank = "No Rank";
if(UserID != null)
{
    userRank = Rank;
}

//or

var userRank = UserID != null ? Rank : "No Rank" 

After

var userRank = UserID?.Rank ?? "No Rank";




do this in the constructor in C# 5 or less. C# 6 introduces Auto-property initializers that enable you to assign a default value for a property as part of the property declaration. This is how using auto-property initializers changes the look of the Person class:
public class Person
{
    public int PersonId { get; set; }
    public string FirstName { get; set; } = string.Empty;
    public string LastName { get; set; } = string.Empty;
    public string FullName { get { return string.Format("{0] {1}", FirstName, LastName); } }
    public DateTime DateCreated { get; set; } = DateTime.UtcNow;
    public DateTime BirthDate { get; set; }
    public ICollection<Qualification> Qualifications { get; set; } = new HashSet<Qualification>();
}

2. Expression bodied members

The FullName property in the Person class is readonly. There is no set accessor for the property. The value is generated from an expression in the get accessor. In C# 6, this expression can be used in the same way as the auto-property initializer, reducing the syntax down a bit:
public string FullName => string.Format("{0} {1}", FirstName, LastName);
The => sign does not denote a lambda expression in the same way as if it is being used with LINQ or any other delegate-based scenario. You can also use this approach to define the body of a method. For example, you might choose to expose a person's age as a method called GetAge() like this:
public TimeSpan GetAge()
{
    return DateTime.Now - BirthDate;
}
You can now replace this with an expression body function like so:
public TimeSpan GetAge() => DateTime.Now - BirthDate;

3. Getter-only auto-properties

When you use auto implemented properties in C# 5 and lower, you must provide a get and set. If you want the property value to be immutable, you can use the private accessor on the setter, but that has always been considered to be a bit of a hack. With C# 6, you can now omit the set accessor to achieve true readonly auto implemented properties:
public DateTime BirthDate { get; }

4. String interpolation

Up until now, I have used string.Format to generate the FullName value in the Person class. I've always foundstring.Format a little clumsy to use although I would prefer to use it rather than have bunch of concatenation operators dotted around my code. A new feature named string interpolation provides a large improvement (in my opinion) in this area. Rather than filling placeholders with indexes then provide an array of values to be slotted in at runtime, you provide the source of the parameter value instead, and the string.Format call is replaced by a single$ sign. This is how the FullName property declaration looks when using string interpolation in the expression body instead:
public string FullName => $"{FirstName} {LastName}";
Apart from this saving a number of key strokes, it should also minimise (if not remove) the possibility ofFormatExceptions being generated from inadvertently supplying too few values to the argument list.

5. Null-conditional operators

var people = new List<Person>();
var name = string.Empty;
if(people.FirstOrDefault() != null)
{
    name = people.First().FullName;
}
How many times have you written code that checks for null to prevent a possible NullReferenceException when attempting to reference a member on an object? If the answer is "way too many", you will probably grow to love thenull conditional operator, which is a simple question mark ? placed just before member you want to reference:
var people = new List<Person>();
var name = people.FirstOrDefault()?.FullName;
If people.FirstOrDefault() returns null, evaluation is terminated without any exceptions being raised, and null is assigned to the name variable. Now that's a useful addition to the language! One thing to be aware of - if you assign a value type to an expression that uses a null conditional operator, the result will be a nullable type.

6. Using static

I'm not sure I've made my mind up about this one. But here it is. This feature provides a shortcut to accessing static methods on classes by importing the name of the class via a using directive qualified by the static keyword. For example, this is how you would do that with the System.IO.File class, which includes quite a number of static utility methods:
using static System.IO.File;
Now you can use the static methods without having to use the class name:
var file = @"C:\test.txt";
if (!Exists(file))
{
    Create(file);
}
The System.Text.RegularExpressions.Regex class also houses a range of static methods:
using static System.Text.RegularExpressions.Regex;
...
...
Replace("input", "pattern", "replacement");
I'm not entirely sure what problem this feature is intended to solve. Chances are that I will forget to use this at all. Utility method names are very similar - ReplaceCreateDelete, and if you are using Regex and File (as an example) in the same file, you will find yourself having to disambiguate between methods across classes that have the same name and signature (like Replace).

7. Index initializers

This feature provides a new way to initialize index-based collections such as dictionaries. Previously, you might do this:
Dictionary<int, string> dict = new Dictionary<int, string>
{
    {1, "string1" },
    {2, "string2" },
    {3, "string3" }
};
Now you can do this:
Dictionary<int, string> dict = new Dictionary<int, string>
{
    [1] = "string1",
    [2] = "string2",
    [3] = "string3" 
};
Apart from this blog post, I wonder if I'll ever get to use this new feature.

Summary

This post has reviewed most of the new features in C# 6 that the average ASP.NET developer is most likely to use or encounter. Personally, I can see myself using the first 5 features regularly, but I am yet to be convinced about the benefits of the last two, and will most likely forget that they are available.

No comments:

Post a Comment