Skip to main content

New features of C# 6.0

If you already had the opportunity to look over the new features of C# 6.0 than you may not be so interested to read this post. Otherwise, this post is perfect for you.
The main scope of this post is to take a look over new features of C# 6.0 that are already available and identify use cases where we can use them with success.

Auto-property initializer
Starting from now we will be able to set a default value of a property directly. We don't need anymore to initialize the value from constructor.
On top of this, we can set a default value for a properties that have only a getter, without a setter. In this way we can replace the read only fields that are public exposed.
  
 public class Foo  
 {  
     public int Value { get; set; } = -1;  
     public string Name { get; } = "Tom";   
 }  

This is not all, on top of this, we can set the default value of a property in a constructor even if we don't have a setter. This is a big change from the old C# language.

public class Foo  
 {  
     public int Value { get; set; } = -1;  
     public string Name { get; }  
     
     public Foo(string name)
     {
          Name = name;
     }
 }  

A nice use case where this can be used with success is when we want to have read only properties, that are set only on constructor. For example when we read a configuration from a file that will be later used in our system.

Null-conditional operators
How many times you had a IF where you would check if a variable is null or not.
I know what you are thinking now. We have ?: operator that allow us replace the IF with a shorter notation.
Yes this is true, but how nice would be to be able to execute a specific code only if the variable is not null, otherwise to return the default value (null) in our case.
This feature is now supported in C# using ? operator. This would allow us to remove the null check, and write directly the code that we want. On top of this, this new operator can be connected with others operators and connected in a 'pipe', like in the below sample.
string name = person?.Name;
string name = person?.Name ?? "Unknown";
char firstLetterOfName = person?.Name?[0]; 
This can be very useful in the moment when we want to access the value of a property but we are not sure if the root of the instance is null or not. This operator will simplify the way how we can check if a property, field or a return value of a method is null or not. But in the same time, bugs could be hidden because of this operator. It is a nice feature but use if with precaution.

Expression-bodied function members
How many times you had a method with only one line of code. In this cases you had to need a lot of "{" and "}" to declare and manage all of them.
Now, you can declare the body of this messages like a lambda expression with only one line of code. This means that we can use directly the "=>" operators.
public sting FullName() => return Name1 + " " + Name2; 
public static int Sum(int a, int b) => return a+b;
public static void SetInstance(object obj) => this.instance = obi; 
public int Count => return this.total;  
We can do this mechanism for operators,  index of even for properties.
I see this features useful for classes that expose a lot of properties that are read from different sources or in the case when we have classes for validation purpose. Where each method contains only a single line and validate a specific use case.

Using Static
I don't know if you are using static methods in your code, but a lot of helper methods are written as static methods. Sometimes can be pretty annoying to write Math.Sqrt each time when you need it.
The new version of C# allow us to use the using attribute to import the static methods from a class. When we are doing this, the static methods from that class can be accessed directly without specifying the class where are declared. This can be done even for extensions methods, as long as we have the wright context to execute them.

using static System.Console;
using static System.Math;
using static System.Linq.Enumerable; 

class Foo
{
    public void Do()
    {
        WriteLine(Sqrt(25)); 
        var range = Range(10, 100);
        range.Where(...);
   } }
Be aware how you use this feature in combination with extension methods. For extension method the instance used by extension method will be used directly by the current object. In our case is 'this' in the first case and range in the second.
I already see this feature used for cases when we have a lot of helper methods.

String Interpolation
String.Format is great. It can help us a lot to create more readable code especially when we need to format our code. But it is pretty annoying to see a string like this "{0}:{1} message {2} where {3} because of {4} in the case of {5}, {0}" and try to count the position of each parameter that will be used in the string.Format expression.
Now, we can use directly the property or field name when we need to format our string. The syntax is very simple and useful.
string message = $"{DateTime.Now}:{error.Level} message {message}..";
It is similar with Razor syntax. Each {} will be interpreted as a block of code, where you can do anything, even 2+2 for example.

Exception Filter
The new syntax is allowing us to enter in a catch block only of a custom rule is applied. We can define our own rules as methods that accept the exception as parameter and returns a Boolean.

public class ExceptionFilters
    {
        public void Do()
        {
            try
            {

            }
            catch (ArgumentNullException ex) 
                when (CustomCheck(ex))
            {
                
                throw;
            }
        }

        private bool CustomCheck(ArgumentNullException ex)
        {
            return true;
        }

        public void DoLogHack()
        {
            try
            {

            }
            catch (ArgumentNullException ex)
                when (Log(ex))
            { }
            catch (AccessViolationException ex)
                when (Log(ex))
            { }
        }

        private bool Log(Exception argumentNullException)
        {
            Trace.WriteLine("Exception");
            return false;
        }
    }
The code in the catch block will not be called if the when condition is not satisfy. It works great for scenarios when you want to combine this with logging control, as in the above example.
This new feature can be useful to reduce the number of IFs from the catch blocks. But use with precaution because you don't want to miss some exceptions.

Await in catch and finally
 Finally we have async support in catch and finally. Even this looks like a small improvement, behind the scene there was a lot of work to support this.
 public class AwaitInCatchandFinally
    {
        public async void Do()
        {
            try
            {
                await GetAsync();
            }
            catch (Exception)
            {
                await GetAsync();
            }
            finally
            {
                await GetAsync();
            }
        }

        private async Task<int> GetAsync()
        {
            Thread.Sleep(1000);
            return 0;
        }
    }

Can be used with success to control when a catch is called.

Index initializers
I will let the sample code to describe this new features and the real value of it.

 public class DictionaryInit
    {
        #region Before

        public Dictionary<int, string> iQ = new Dictionary<int, string>()
        {
            {1, "A"},
            {2, "B"}
        };

        #endregion

        #region After

        public Dictionary<int, string> iQAfter = new Dictionary<int, string>()
        {
            [1] = "A",
            [2] = "B"
        };

        #endregion
    }
It is a lot simple to initialize dictionary of other object like them.

nameOf
When we need to access a name of a property or a method we usually use reflection or other mechanism. Starting from now we can use this new string literal that will resolve the name of a property, field and so on to a string that represents the name of it. Without reflection or other hacking.
public class NameOfFieldParameterOrProperty
    {
        private int DogName { get; set; }

        public void DoParameter(string name)
        {
            if (name == null)
            {
                throw new ArgumentNullException(nameof(name)); // "name"                
            }
        }

        public void DoProperty()
        {
            string propertyName = nameof(DogName);
            string propertyNameCount = nameof(Int32.MinValue);
        }

        public void DoField()
        {
            int myHeroField;

            string nameOfField = nameof(myHeroField);
        }
    }

We saw what C# 6.0 brings to us. If we want to find more please visit the official page: https://github.com/dotnet/roslyn/wiki/New-Language-Features-in-C%23-6

Comments

Popular posts from this blog

Windows Docker Containers can make WIN32 API calls, use COM and ASP.NET WebForms

After the last post , I received two interesting questions related to Docker and Windows. People were interested if we do Win32 API calls from a Docker container and if there is support for COM. WIN32 Support To test calls to WIN32 API, let’s try to populate SYSTEM_INFO class. [StructLayout(LayoutKind.Sequential)] public struct SYSTEM_INFO { public uint dwOemId; public uint dwPageSize; public uint lpMinimumApplicationAddress; public uint lpMaximumApplicationAddress; public uint dwActiveProcessorMask; public uint dwNumberOfProcessors; public uint dwProcessorType; public uint dwAllocationGranularity; public uint dwProcessorLevel; public uint dwProcessorRevision; } ... [DllImport("kernel32")] static extern void GetSystemInfo(ref SYSTEM_INFO pSI); ... SYSTEM_INFO pSI = new SYSTEM_INFO(...

ADO.NET provider with invariant name 'System.Data.SqlClient' could not be loaded

Today blog post will be started with the following error when running DB tests on the CI machine: threw exception: System.InvalidOperationException: The Entity Framework provider type 'System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer' registered in the application config file for the ADO.NET provider with invariant name 'System.Data.SqlClient' could not be loaded. Make sure that the assembly-qualified name is used and that the assembly is available to the running application. See http://go.microsoft.com/fwlink/?LinkId=260882 for more information. at System.Data.Entity.Infrastructure.DependencyResolution.ProviderServicesFactory.GetInstance(String providerTypeName, String providerInvariantName) This error happened only on the Continuous Integration machine. On the devs machines, everything has fine. The classic problem – on my machine it’s working. The CI has the following configuration: TeamCity .NET 4.51 EF 6.0.2 VS2013 It see...

Navigating Cloud Strategy after Azure Central US Region Outage

 Looking back, July 19, 2024, was challenging for customers using Microsoft Azure or Windows machines. Two major outages affected customers using CrowdStrike Falcon or Microsoft Azure computation resources in the Central US. These two outages affected many people and put many businesses on pause for a few hours or even days. The overlap of these two issues was a nightmare for travellers. In addition to blue screens in the airport terminals, they could not get additional information from the airport website, airline personnel, or the support line because they were affected by the outage in the Central US region or the CrowdStrike outage.   But what happened in reality? A faulty CrowdStrike update affected Windows computers globally, from airports and healthcare to small businesses, affecting over 8.5m computers. Even if the Falson Sensor software defect was identified and a fix deployed shortly after, the recovery took longer. In parallel with CrowdStrike, Microsoft provi...