3 features of C# 7 that may convince you to upgrade

- Emran Hussain,
12 March 2017, Sunday, 5:21:16 PM

When C# 6 came out to the market, I was thinking, why should I bother. What is so nice about C#6 so that I need to upgrade my VS 2013 to VS 2015. I found one, and that was that was compelling enough for me to do the switch. It was nameof(..) operator. Yes, I was highly excited to replace all of my magic strings with nameof(..). All places where I had to use hard coded property names (WPF ViewModels, dependency properties...etc) was looking nice and strongly typed with nameof(..).

This time, with c#7, I was looking for at least one feature that can convince myself to do the upgrade again. Fortunately, instead of one, I found many. I am not talking about just new features. Of course, you will find all of them here: https://blogs.msdn.microsoft.com/dotnet/2016/08/24/whats-new-in-csharp-7-0

I am talking about some killer feature which is convincing enough for me to pay for the upgrade.

#1 : Tuples

Readability Benefit

Yes, it is the very typical demand to return more than one value from a method. In order to achieve that goal, we create a Value Container (DTO) class/struct to be the return type of that method. But, how many classes you want to create for all of your methods in a big solution? It can be hundreds! Of course, I am not advocating a pattern where you will create service classes with a list of methods. Rather, I am a purist, and I favor strong Object Oriented Programming where an Entity should have the responsibility of performing something IF the entity has the information about that responsibility. (GRASP - Information Expert Pattern.)

Even though, you will have the need to create a class just for return types in many scenarios. So, in order to solve that problem, we usually use Tuples. And using Tuple has a Cost. Tuple members are named as Item1, Item2, ...ItemN.

When you use Tuple as a return type at the time when you write your code for the first time, you do not see the problem, but it becomes a maintenance headache when you try to change your code at the consumer layer (consumer of the method that returns Tuple). You would simply need to navigate to the method all the time just to find out Item1 means what, Item2 means what! That is a painful way, and we needed a solution to this problem.

Microsoft realized that and given us the solution. Now, you can return multiple named values from a method using C# 7 Tuple, and you can deconstruct the Tuple with a set of named variables in the consumer layer.

Wow! That must be more than what I could ask. I have copied the following example from MSDN Blog:

(string, string, string) LookupName(long id) // tuple return type

{

    ... // retrieve first, middle and last from data storage

    return (first, middle, last); // tuple literal

}

The method now effectively returns three strings, wrapped up as elements in a tuple value.

Now the recipient of that tuple have more descriptive names to work with:

var names = LookupName(id);
WriteLine($"found {names.first} {names.last}.");

You can also specify element names directly in tuple literals:

 return (first: first, middle: middle, last: last); // named tuple elements in a literal

So, if you embrace this feature, this is high time you deleted a huge number of small DTO classes from your project.

Pain Point

As soon as I read that article, I jumped to download the Visual Studio 2017 RC. Yes, the first time in my life, I installed RC version of Visual Studio in my life. I am always a fan of the official release. Anyway, I realized that to use that feature, I need to add a package named System.ValueTuple from Nuget. Seriously ? I did not like that idea. What was the problem to integrate this part into the compiler or .Net directly. It is not fun to add Nuget package in every single project in a large solution just to use a language feature.

#2 : Generalized async return types

So far, we could return Task, Task<T> and void from an async method. On occasions when the result is known immediately, we are still bound to instantiating a Task, even though no task is required to determine the result. A Task is a reference type, and that costs memory allocation.

For example, here is a method that downloads a web page from a given URL.

public async Task<string> DownloadWebpage(string url)
{
   if(url == null)
     return string.Empty;
   else
      return await Task.Run<string>(()=> fetchUrl(url));
}

If the given URL is null, we do not need to fetch the URL and there is no need for an asynchronous thread to fetch the web page. But, as the return type is Task<string>, it a Task<T> is still needs to be instantiated. And that is very expensive in memory. Now, C# 7 gives us the ability to define custom return types on Async methods. Using that new feature, we can rewrite our web page downloading code as follows:

public async ValueTask<string> DownloadWebpage(string url)
{
   if(url == null)
     return string.Empty;
   else
      return await Task.Run<string>(()=> fetchUrl(url));
}

As the ValueTask<T> is a struct, (a value type instead of a reference type), it can drastically reduce the number of memory allocations. Thus we can get the significant performance gain.

Pain Point

Same like Tuple, we need to add NuGet package reference (System.Threading.Tasks.Extensions) to use this feature. Just to use a language feature, we need to add a reference to this package in every project. I do not like this idea.

#3 : Local functions

Here is an example of a local function.

private static void Main(string[] args)
{
   
    int Square(int number)
    {
        return number * number;
    }
 
    Console.WriteLine(Square(100));
}

Well, initially I was thinking, what is the extra benefit in a local function? I can achieve the same goal by using Func<T,T> delegates. Can't I ? Moreover, I was thinking, what an ugly way of writing code. A method should not be complicated; a method should do only one thing. An obese method with many local functions simply stinks. Whenever we see a method is doing lots of things, we should think about encapsulating the logic to a separate class. But, later, I realized that, maybe, Microsoft is not advocating bad code practices, rather it is solving a problem when we would need a local function. Then, again, why it is beneficial over a Func<T,T> delegate! Then I found the following article where it is explained nicely.

https://github.com/dotnet/roslyn/issues/3911

The bottom line is, the local function is more efficient (performance wise) than a local lambda delegate. When I heard the word ‘performance,' I was sold.

Here is the answer from that page:

You want a helper function. You are only using it from within a single function, and it likely uses variables and type parameters that are in scope in that containing function. On the other hand, unlike a lambda, you don't need it as a first class object, so you don't care to give it a delegate type and allocate an actual delegate object. Also, you may want it to be recursive or generic, or to implement it as an iterator.

The answer given by a stack overflow member named ‘svick’ was splendid:
http://stackoverflow.com/a/40949214/647459

© All content, photographs, graphs and images in this article are copyright protected by SpiceLogic Inc. and may not, without prior written authorization, in whole or in part, be copied, altered, reproduced or published without exclusive permission of its owner. Unauthorized use is prohibited.
Last edited on : 8 Apr 2017
Please feel free to share your comment.