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))

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.


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: 39792


- 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


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;

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


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


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


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


- 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


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

Recent Comments

Pam 30/08/2017 11:30
In response to Sending Email in Razor Pages
Mike, RazorPages sound like a nice choice for somebody still working in ASP classic who wants to to...

Robby Robson 15/08/2017 00:43
In response to Routing in Razor Pages
Mike: great stuff. Now that .Core Standard 2.0 is formally out, how soon will you rewrite your book...

Satyabrata Mohapatra 28/07/2017 08:59
In response to Sending Email in Razor Pages
Bit off topic, but congratulation sir for your MVP award. You deserve it !!!...

Satyabrata Mohapatra 23/07/2017 16:43
In response to Razor Pages - The Elevator Pitch
@Dale Severin You can continue to build apps using asp.net web pages....

Satyabrata Mohapatra 23/07/2017 16:40
In response to Sending Email in Razor Pages
Thanks for sharing...learned a lot...

Gfw 22/07/2017 11:53
In response to Sending Email in Razor Pages
Question... Does System.Net.Mail support SSL?...

Dale Severin 20/07/2017 03:38
In response to Razor Pages - The Elevator Pitch
I work with razor web pages extensively. I appreciate the rapid development it permits me to I am as...

Obinna Okafor 14/07/2017 01:19
In response to Routing in Razor Pages
Thank you, Mike. Good post....

Satyabrata Mohapatra 11/07/2017 16:02
In response to Routing in Razor Pages
Very powerful routing system!!...

Cyrus 05/07/2017 03:41
In response to Razor Pages - Getting Started With The Preview
How can I trim packages and services as much as possible to use just razor pages? I don’t want to to...