Thursday, September 3, 2015

15 Cool New Features in C# 6.0

The first release of the C# language was in 2002 and then in 2005 version 2 released. It gave us Generics. In 2007, the C# language gave us Linq features, including lambda expressions, implicit typing, a query syntax and var keyword. In 2010, the release of version 4 introduced the dynamic keyword and the dynamic language runtime. And then 2012 brought us version 5 of the language. It gave us the async and await keywords, which make async code much easier to read and write, and in today's world where the async programming model is used nearly everywhere from the server to the client. Compared to the previous release, the language features introduced in this version might seem underwhelming. And partly that's because C# is now over 13 years old; it's a somewhat mature language has major features that have been added over the years. They give us the ability to write less code than we had to write before.



Here is the 15 cool new features in C# 6.0 According to Roslyn some features are planned and might be available in the future.

1. Auto-Property Initializers

In early version of c# if we want to set a default value for a property in a class, we do this in the constructor. In C# 6.0 using Auto-property initializers we can assign a default value for a property as part of the property declaration itself.

// Old way
class Program
{
    public Program()
    {
        MyProperty = 10;
    }

    public int MyProperty { get; set; }
}

// New way
class Program
{
    public int MyProperty { get; set; } = 10
}

2. Using static

With static members you don't need an instance of an object to invoke a method, you just use the typename, a dot, a static method name, and apply parentheses and parameters. This feature allows us to access the static methods inside a class directly without speifying its class name. Usually we use Convert.ToInt32 to convert a value to integer. But using this feature we can just use ToInt32 to convert.

// Old way
namespace TestApp
{
    class Program
    {
        static void Main(string[] args)
        {
            var value = Convert.ToInt32("2015");
        }
    }
}

// New way
using static Convert;

namespace TestApp
{
    class Program
    {
        static void Main(string[] args)
        {
            var value = ToInt32("2015");
        }
    }
}

// Some more samples,
using static System.Console; 
using static System.Math;

class Program 
{ 
    static void Main() 
    { 
        WriteLine(Sqrt(25)); 
    } 
}

3. Dictionary Initializers

Ever since C# version 3 came around, we've had the ability to initialize collections like lists and dictionaries using the key value pairs are surrounded with curly braces. With C# 6.0 we can achieve the same result, using key value inside of square brackets and a sign of value using an equal sign.

// Old way
Dictionary dict = new Dictionary<int, string>
{
    {1, "Apple" },
    {2, "Microsoft" },
    {3, "IBM" }
};

// New way
Dictionary dict = new Dictionary<int, string>
{
    [1] = "Apple",
    [2] = "Microsoft",
    [3] = "IBM" 
};

4. Getter-only auto-properties
When we use auto implemented properties in old vesion of c#, we must provide both get and set. If you want the property value should not be set, you can use the private accessor on the setter, With C# 6.0, you can now omit the set accessor to achieve true readonly auto implemented properties:

// Old way
public int MyProperty { get; private set; }

// New way
public int MyProperty { get; }

5. Null-conditional operators (?.)

This is one of the cool feature in c# 6.0. Usually we use if condition before using it to execution. But using this feature we can check the value is null or not in a single line and proceed the execution if it is not null. It help us to avoid the NullReferenceException.

// Old way
public string Truncate(string value, int length)
{
    string result = value;
    if (value != null)
    {
        result = value.Substring(0, value.Length - 1);
    }

    return result;
}

// New way
public string Truncate(string value, int length)
{          
    return value?.Substring(0, value.Length - 1);
}

Some more samples,
int? length = customers?.Length; // null if customers is null
Customer first = customers?[0]; // null if customers is null 
int length = customers?.Length ?? 0; // 0 if customers is null

6. await in catch and finally block

In c# 6.0 the await keyword can be used inside catch or finally block. Usually we would write log when any exception occured inside catch block itself. In those times we no need to wait for that execution to be completed before going to next line of execution. So using the await keyword those execution will be asynchronous.

try
{

}
catch (Exception)
{
    await LogManager.Write(ex);
}
finally
{
    await LogManager.Write("Done");
}

7. Declaration expressions

Using this feature we can declare local variable in an expression itself instead of declaring globally. But the scope of that variable will be inside the loop.

// Old way
int parsed;
if (!int.TryParse("12345", out parsed))
{ 
}

// New way
if (!int.TryParse("12345", out int parsed))
{
}

8. Primary Constructor

Using this feature the property values can be initialized directly with the help of another new feature Auto-Property Initializers that we have seen in this post, without using default constructor and writing much of code to it. When using a primary constructor all other constructors must call the primary constructor using :this().

// Old way
public class StoredProcedureInfo
{

    private StoredProcedureInfo(string connectionName, string schema, string procedureName)
    {
        this.ConnectionName = connectionName;
        this.Schema = schema;
        this.ProcedureName = procedureName;
    }

    public string ConnectionName { get; set; };
    public string Schema { get; set; };
    public string ProcedureName { get; set; };
}

// New way
private class StoredProcedureInfo(string connectionName, string schema, string procedureName)
{
    public string ConnectionName { get; set; } = connectionName;
    public string Schema { get; set; } = schema;
    public string ProcedureName { get; set; } = procedureName;
}

9. Exception filters

This feature allow us to specify a condition on a catch block. Based on that condition the catch block will be executed.

try
{
}
catch (Exception ex) if (UserPermission == Permission.Administrator)
{
}
catch (Exception ex) if (UserPermission == Permission.Requester)
{
} 

10. Expression-bodied function

Expression-bodied function members allow methods, properties, operators and other function members to have bodies as lambda like expressions instead of statement blocks. It helps reducing lines of codes.

// Old way
public int Multiply(int a, int b)
{
    return a * b;
}

// New way
public int Multiply(int a, int b) = > a * b;

// Old way
public int WriteLog(string log)
{
    LogManager.Write(log);
}

// New way
public int WriteLog(string log) => LogManager.Write(log);

// Some more samples,
public double Distance => Math.Sqrt(X + Y); // property
public void Execute() => Math.Sqrt(25); // method

11. String Interpolation

This feature is one of an addition to the string format technique in c#. So far we used + sign or string.format to format a string. But in this feature we can directly use the value to be concatinate inside the string itself using \{} symbol. Any condition can be used inside the braces.

// Old way
public string FormatString(int value)
{
    return "Total # of tickets: "+ value + " tickets";
}

public string FormatString(int value)
{
    return string.Format("Total # of tickets: {0} tickets", value);
}

// New way
public string FormatString(int value)
{
    return "Total # of tickets: \{(value <= 1 ? "ticket" : "tickts")}";
}

// Some more samples,
var s = "\{person.Name} is \{person .Age} year\{(person.Age == 1 ? "" : "s")} old"; 

12. nameof

Used to obtain the simple (unqualified) string name of a variable, type, or member. When reporting errors in code instead of hard code it.

// Old way
public void SaveData()
{
    try
    {
    }
    catch (Exception ex)
    {
        this.WriteLog("SaveData", ex);
    }
}

// New way
public void SaveData()
{
    try
    {
    }
    catch (Exception ex)
    {
        this.WriteLog(nameof(SaveData), ex);
    }
}

13. Literals and Separators

When initializing fields and properties and variables with numerical values, we have a new binary literal syntax we can use, 0b. We can write binary values with a 0b prefix and then use just ones and zeros to specify which bits are on and off. This can lead to more readable code.
public byte code = 0b01011011010;
Another feature we have for numeric literals will be the ability to use an underscore as a separator. It's much easier to look at a value and see it as in the billions or the millions when we have an underscore separating the digits instead of just a long string of numbers. The C# compiler doesn't actually care where you use the separator, the separator can appear anywhere after the first leading digit.

public long value = 1_000_000_000;

14. Event Initializer

C# 6.0 will now allow us to wire up event handlers as part of an object initialization syntax. Before a version 6 of the language, this event wire up syntax would be illegal. I just always have to remember to use the += operator to wire up an event. Trying to assign directly to an event using an equal sign is still illegal. Events need to encapsulate the delegates that they hold inside, so from the outside we can only use += and -= to add and remove delegates respectively. In an initializer you'd want to be using += to add delegates and listen for an event to fire.

public class Person
{
    private int _age;
    public int Age
    {
        get
        {
            return _age;
        }
        set
        {
            _age = value;
             OnAgeChanged(EventArgs.Empty);
        }
    }

    public string Name { get; set; }

    public event EventHandler AgeChanged;

    protected virtual void OnAgeChanged(EventArgs e)
    {
        if (AgeChanged != null)
        {
            AgeChanged(this, e);
        }
    }
}

// Old way
class Program
{
    static void Main(string[] args)
    {
        var pers = new Person()
        {
            Name = "Venkat"
        };
        pers.AgeChanged += pers_AgeChanged;
 }

    static void pers_AgeChanged(object sender, EventArgs e)
    {
        Console.WriteLine("Changed");
    }
}

// New way
class Program
{
    static void Main(string[] args)
    {
        var pers = new Person()
        {
            Name = "Venkat",
             AgeChanged += pers_AgeChanged
        };
    }

    static void pers_AgeChanged(object sender, EventArgs e)
    {
        Console.WriteLine("Changed");
    }
}
15. params and Ienumerable

In C# version 6.0 we can use the params keyword with IEnumerable instead of using an array.

// Old way
void Foo(params int[] a) 
{
}

Foo(10,2,4,22);

// New way
void Foo(params IEnumerable<int> a) 
{
}

Foo(10,2,4,22);

Happy Coding!

No comments:

Post a Comment