C# 6

C# 6 Features – Expression-bodied Members

I have finally gotten around to looking into C# 6. It was released in July 2015 and available starting in .Net Framework 4.6, but I just hadn’t had any occasion to use it. In order to “force myself” to dig into it a little more, I decided to write a series of blog posts about the new features. The first one out of the gate is Expression-bodied Members.

Expression-bodied Members are just a syntactic sugar on the language. I’m not angry about things that are syntactic sugar. In fact, one of my favorite things about C# 3 was automatic properties, so I’m all in. In reality, it is just about expressing intent more clearly and more succinctly. Here is a very simple example of a method that uses this new feature.

public int DoubleANumber (int input) => input*2;

In this case, I’ve defined a public method that takes an integer and returns an integer. As we are reading left-to-right, there is nothing weird yet. However, after the method name declaration, we change it up and throw the “Anders Operator” aka “Hash Rocket” aka “LINQ Symbol” aka “Goes To” aka “=>” into the mess. Just like LINQ, you can put an expression right afterwards and that is what is evaluated. We are missing the curly braces, sure, but we are also missing a return statement. You don’t need it.

You can also use this simple syntax for properties. Take a look at the following class:

public class Person
{
     public string FirstName {get;set;}
     public string LastName {get;set;}
     
     public string FullName => string.Format("{0} {1}", FirstName, LastName);
}

The FullName property is now just a read-only expression. The alternative would have looked like this:

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

Even if you one-lined the FullName property, it would not be as clean as the Expression-bodied version

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

Fantastic. We’ve seen a way to clean up our code a bit, no down side, right? Well, of course there is a down side. This is only really useful and clean-looking if you have a very simple one-liner to express. If you ramp this guy up a bit, it starts to break down.

// DOES NOT COMPILE
public class Ugh
{
    public int DoLotsOfStuff(int input) =>
        input += 2;
        input = input * 2;
        Math.Pow(input, 2);
}

This doesn’t even compile, for probably very obvious reasons. You can’t do a bunch of work on separate lines and then just hope the last evaluation is what is returned. The error you get is “Invalid token ‘=’ in class, struct, or interface member declaration”. The reason being that C# thinks that the method is just public int DoLotsOfStuff(int input) => input += 2; After that, it is trying to figure out how input = input * 2; makes sense as a free standing line within the class. That isn’t how you declare a method, a property, or a field, so C# freaks out. Of course you could jam all of that on one line, but it may start to get confusing the more you try to do.

So, Expression-bodied Members can be a nice clean way to express your code simply. However, the danger here is that developers could try to play “code golf” to get their code to fit on one line. That would really decrease readability, which defeats the entire purpose. So, I feel like this is a feature to use carefully and sparingly.

2 comments C# 6 Features – Expression-bodied Members

mgroves says:

I noticed you used string.Format in your example. Maybe you’re going to get to this in a later post, but definitely check out the string interpolation.

Your example becomes even more succinct:

public string FullName => return $”{FirstName} {LastName}”;

Pete says:

Thanks, Matt. Yeah, I’m definitely going to cover that, as it was also one of the new features in 6. I plan on going over all (or almost all) of them in the coming weeks.

Leave a Reply

Your email address will not be published. Required fields are marked *