7 C# 6.0 Features That Every ASP.NET Developer Should Know About

4.81 (27 votes)

Visual Studio 2015 introduces a completely new version of ASP.NET, but it also includes version 6 of the C# language. Previous new versions of C# have heralded substantial changes like the introduction of async and await in version 5, dynamic in version 4, LINQ in version 3 and so on. There are no major feature changes or introductions in version 6, but there are a number of syntactical improvements that you are likely to use on a daily basis. Here's a rundown of them.

I will start with a pair of classes that might form a very simple model in any application:

public class Person
{
    public Person()
    {
        FirstName = string.Empty;
        LastName = string.Empty;
        DateCreated = DateTime.UtcNow;
        Qualifications = new HashSet<Qualification>();
    }
    public int PersonId { get; set; }
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public string FullName { get { return string.Format("{0} {1}", FirstName, LastName); } }
    public DateTime DateCreated { get; set; } 
    public DateTime BirthDate { get; set; }
    public ICollection<Qualification> Qualifications { get; set; } 
}
public class Qualification
{
    public Qualification()
    {
        Awardees = new HashSet<Person>();
        Name = string.Empty;
    }
    public int QualificationId { get; set; }
    public string Name { get; set; } 
    public DateTime WhenAwarded { get; set; }
    public virtual ICollection<Person> Awardees { get; set; } 
}

The model features a Person class and a Qualification class, and a many-to-many relationship between them. The associations between the classes are declared as virtual, indicating that they are navigation properties in a Code First model intended for use with Entity Framework. Auto properties have largely been used because there is no logic to be executed when setting or getting the property values. The FullName property in the Person class is constructed from the FirstName and LastName properties. Default values for some properties are defined in class constructors. The first three new C# 6 features are all concerned with improving syntax when defining simple classes like these. I will look at how they affect the Person class.

1. Auto-property initializers

If you want to set a default value for a property in a class, you 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 found string.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 of FormatExceptions 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 the null 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 - Replace, Create, Delete, 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.

 

You might also like...

Date Posted:
Last Updated:
Posted by:
Total Views to date: 36205

19 Comments

- James Chaney

Question on #5 - I don't see where this gets you out of a NullReferenceException if people.FirstOrDefault() returns null then name is assigned null and if you try to use name then won't you still get the NullReferenceException?

- Mike

@James

Yes - if, for example, you tried to do a Replace() on name, you would get an exception if it is null. The purpose of the new syntax is not to remove the possibility of a NullReferenceException, but to reduce the amount of code you need to prevent one arising e.g.
var name = people.FirstOrDefault() != null ? people.First().FullName : null;

becomes
var name = people.FirstOrDefault()?.FullName;

And you can use it in conjunction with the null-coalescing operator to produce a shorter syntax:
var name = people.FirstOrDefault()?.FullName ?? "None given";

- Lokesh

Excellent Article..!!
Thanks Mike :)

- chandradev

very nice article. Thanks for sharing with us.

- aaron

#6 enables a less-verbose functional programming style

- Gayan

Great Article thanks

- Vikas Rana

Great Article !!
Thanks for sharing Mike.

- henk

I think you have a typo in your article:
public string FullName { get { return string.Format("{0] {1}", FirstName, LastName); } }

- sandeep

very good article, i like it........keep writing such quality article in future. thx Mike.

- chandra sekhar

Great Mike..!!

Thanks for sharing.. Keep posting new things regards dotnet.

- Hassan.cs

Lovely Overview ! Stay Blessed :)

- Don

In addition to the typo in:

public string FullName { get { return string.Format("{0] {1}", FirstName, LastName); } }

Shouldn't you use the new string formatting:

public string FullName { get { return $"{FirstName} {LastName}"; } }

- Mike

@Don,

Fixed the typo - thanks for that. But no - I didn't want to use the new formatting at that point in the piece. Otherwise I would have to explain it, thereby introducing two concepts at the same time.

- Niks Shine

Hi,

I am going to start learning ASP.net MVC. Just for the guidance purpose, I would like to know which C# feature(s) one should be aware about beforehand, to learn ASP.net MVC framework.

Thanks Mike!

- Mike

@Niks

I started with the framework and learned what C# I needed to learn as I went along. That worked for me, but might not work for others.

- Tanya

Great Article. I'm using all except 6.

- Ammar

Thanks.

- Nicolas

I got a problem in my class person when I want to do this. Because I don;'t want the fullname into the database.
public string FullName => $"{FirstName} {LastName}" or this public string FullName => ((FirstName + " " + MiddleName).Trim() + " " + LastName).Trim();

InvalidOperationException: No backing field could be discovered for property 'BASIC_WebPortal.Models.ApplicationUser.FullName' and the property does not have a setter. Either use a backing field name that can be matched by convention, annotate the property with a backing field, or define a property setter.

Thank you for the help. This article is great.

- Mike

@Nicolas,

I assume you are trying to use EF 7. If so, see this issue: https://github.com/aspnet/EntityFramework/issues/3822

Recent Comments

Gfw 03/02/2017 09:48
In response to Free SSL Certificates On IIS With LetsEncrypt
I have used WinSimple for about the last 9 months - works great. One thing that you want to make of...

Ted Driver 02/02/2017 13:24
In response to Free SSL Certificates On IIS With LetsEncrypt
This looks great is you have command line access to your web server - what about those of us on Is...

Carl T. 06/11/2016 05:43
In response to Server.MapPath Equivalent in ASP.NET Core
Very succinct and easy to follow. Worked perfectly the first time for me. Thanks!!...

Manoj Kulkarni 04/11/2016 05:47
In response to Entity Framework Core DbContext Updated
Great post....

Sivu 19/10/2016 08:21
In response to Entity Framework Core TrackGraph For Disconnected Data
Oh that's very very very nice ! Thanks for the write up Mike, much appreciated for the taking the to...

Mark 12/10/2016 16:42
In response to ASP.NET Web Pages vNext or Razor Pages
Although "Web Pages" was removed from the roadmap, has it just been renamed to "Razor Pages"?...

Satyabrata 12/10/2016 09:20
In response to Entity Framework Core TrackGraph For Disconnected Data
Nice article. Please write more articles featuring ASP.Net web pages. Thank you...

Julian 26/09/2016 14:27
In response to Loading ASP.NET Core MVC Views From A Database Or Other Location
Fantastic, many thanks Mike! Had got half way down this road before finding your article - saved...

Abolfazl Roshanzamir 14/09/2016 05:36
In response to Loading ASP.NET Core MVC Views From A Database Or Other Location
Nice article. Thanke you so much ....

cyrus 02/09/2016 15:12
In response to ASP.NET Web Pages vNext or Razor Pages
I've got some news. As Damian stated in this link: https://github.com/aspnet/Mvc/issues/5208 “We...