Experimenting with the New Features of C# 6

Introduction and Background

It has been a very long time, and trust me, I am fed up with the “Cool new features of C# 6!” posts already. I mean, each post has the same things, the same topics, the same content and (usually!) the same code blocks to show the thing too. However, I never wanted to write a blog to describe the new things in C#, but now I think I should explain the things that are done “under the hood” for the C# 6’s code. I have gone through many posts and I already know what these new “cool” features are, so I just wanted to test them out and see when they work, how they work, and when they are not going to work. Well definitely, that is something that people aren’t expecting by C# architect team, however, let’s find them out. :-)

Also, it has already been very late for C# 6 to be discussed because C# 7 has already been discussed by the team; you may want to read more about what C# 7 team has on their list. C# 7 Work List of Features.

Anyway, none of them are the last versions, final statements, or “C# 7 must-haves.” They are just what they are trying to inject to C# as per the demand and ideas provided to them on GitHub and other networks that they have.

Enough of C# 7 already, now you have already seen all the features that were introduced in C# 6 and most of you have used those features in your applications. But, did you try to use them in a way they were not intended to be used? I mean, have you tried to use them in a very “unknown” or “uncertain” manner?

Let me share what I think of those features. I would also love to hear what you think of them! :-)

Counting the features of C# 6

Now let me show you a few things about these services, in a way that you were not expecting or you never cared about! These features are definitely interesting, but, a few are useful in one way, and a few are not at all useful in one way. Depends on your project, your perspective, and ideas. So let me start by the very famous (and my favorite C# 6) feature: String Interpolation.

String interpolation

This feature is a great feature, personally saying, this is the best feature that I find on C# 6 features list. What I find easy while using “string interpolation” is, that I don’t have to use String.Format, I don’t have to concatenate the strings, I don’t have to use the StringBuilder at all. What I can do is that I can just simply write the string and it would include the variable data in the string. Now let me show you an example of multiple methods that can be used.
  1. // Creating the private field  
  2. private static string Name = "Afzaal Ahmad Zeeshan";  
  3.   
  4. // Then inside the Main function.  
  5.   
  6. // 1. Using string concatenation.  
  7. Console.WriteLine("Hello, my name is: " + Name);  
  8.   
  9. // 2. Using string format  
  10. Console.WriteLine(string.Format("Hello, my name is: {0}", Name));  
  11.   
  12. // 3. Using string builders  
  13. StringBuilder builder = new StringBuilder();  
  14. builder.Append("Hello, my name is: ");  
  15. builder.Append(Name);  
  16. Console.WriteLine(builder.ToString());  

Technically, their result is same. They all say the same message, and how they do it, we can find that out using the Assembly language (or the MSIL code, if you are a fan of MSIL and not Assembly at the debug time), however, we do know that they present the same value on screen.

ways
            Figure 1: Same string rendered and generated, as a result of many ways.

Their IL benchmark would be different (because internally they are three different ways). That is because, they are different. Their IL generated would be like this:
  1. IL_0000: nop  
  2. IL_0001: ldstr "Hello, my name is: "  
  3. IL_0006: ldsfld UserQuery.Name  
  4. IL_000B: call System.String.Concat  
  5. IL_0010: call System.Console.WriteLine  
  6. IL_0015: nop  
  7.   
  8. IL_0016: ldstr "Hello, my name is: {0}"  
  9. IL_001B: ldsfld UserQuery.Name  
  10. IL_0020: call System.String.Format  
  11. IL_0025: call System.Console.WriteLine  
  12. IL_002A: nop  
  13.   
  14. IL_002B: newobj System.Text.StringBuilder..ctor  
  15. IL_0030: stloc.0 // builder  
  16. IL_0031: ldloc.0 // builder  
  17. IL_0032: ldstr "Hello, my name is: "  
  18. IL_0037: callvirt System.Text.StringBuilder.Append  
  19. IL_003C: pop  
  20. IL_003D: ldloc.0 // builder  
  21. IL_003E: ldsfld UserQuery.Name  
  22. IL_0043: callvirt System.Text.StringBuilder.Append  
  23. IL_0048: pop  
  24. IL_0049: ldloc.0 // builder  
  25. IL_004A: callvirt System.Object.ToString  
  26. IL_004F: call System.Console.WriteLine  
  27. IL_0054: nop  
  28.   
  29. IL_0055: ret  
You can see, that (indirectly) they are all different and execute different functions. What happens, is a "syntactic sugar." They are typically just functions that are executed and compiler allows you to write these simply.

Now coming to the new way of writing the strings with variable content. C# 6 introduces this new way of writing the same message! 
  1. Console.WriteLine($"Hello, my name is: {Name}");  
  2.   
  3. /* Output: 
  4. * Hello, my name is: Afzaal Ahmad Zeeshan 
  5. */  
The output of this is also same… But, how C# 6 does that is a bit of trick now. To find that part out, we will again go back and read the MSIL generated.
  1. IL_0000: nop  
  2. IL_0001: ldstr "Hello, my name is: {0}"  
  3. IL_0006: ldsfld UserQuery.Name  
  4. IL_000B: call System.String.Format  
  5. IL_0010: call System.Console.WriteLine  
  6. IL_0015: nop  
  7. IL_0016: ret  
Um, watching at this MSIL, what do you say? :-) If you pay attention to the highlighted code, this resembles the code that we wrote using the String.Format() method. So what happens is, that this is also a syntactic sugar. There is no addition of anything, it is just what compiler does for you! Compiler simply takes away everything, and generates that previous version of the code. Yet, in a very friendly and simple way. I like it.

Remarks and References:

String interpolation has been adopted by many programming languages by now. Swift by Apple and JavaScript (ECMAScript) is also moving forward to templated strings. I personally feel, since string type data is mostly used, this is a great feature. For more, please read:
Conditional try…catch

Now, I have never used VB.NET, because I was always busy in C# itself but I still hear that VB.NET had this feature way before C# implemented it. The conditional try … catch (or as the team calls them, “Exception filters“) just allows you to handle the exception when a condition is met, I am not going to talk about what they are, instead, I will talk about how you can use them in your code. So basically, if you execute a function that is supposed to have a side-effect, and before handling any further errors, you want to find out if there was a side-effect or did the error occur before the side-effect, you would possibly be left with only one way to check that out!
  1. try  
  2. {  
  3.     // Some code that breaks the execution.  
  4. catch (MyException me)   
  5. {  
  6.     // Just a function to check if value was updated  
  7.     if (field.Updated())   
  8.     {  
  9.         // Log the error and then re throw the exception  
  10.     }  
  11. catch (Exception e)  
  12. {  
  13.     // Re-perform the same for other exceptions.  
  14. }  
As an example of this case, have a look at the following code:
  1. private int field = 25;  
  2.   
  3. public static void Main(string[] args)  
  4. {  
  5.     try {  
  6.         Console.WriteLine("Do you want to change the field?");  
  7.         if (Console.ReadLine() == "yes")  
  8.         {  
  9.             field = 34;  
  10.         }  
  11.         // Just throw the exception  
  12.         throw new Exception();  
  13.     } catch {  
  14.         if (fieldModified())  
  15.         {  
  16.             // Log error, it was thrown after modifying the field.  
  17.         }  
  18.         // Other code...  
  19.     }  
  20. }  
  21.   
  22. public static bool fieldModified() {  
  23.     return (field == 25) ? true : false;  
  24. }  
This try catch would allow us to check if our fields were modified, if not, then we can simply ignore as there were no side-effects.

Now what C# 6 allows you to do is to add a condition outside the block, so that you don’t even have to enter the block itself, and the condition would just check if it needs to go to this block, if not, then exception would continue to grow and later catch blocks would try their luck, finally to the end. Something like this.
  1. try  
  2. {  
  3.     Console.WriteLine("Do you want to change the field?");  
  4.     if (Console.ReadLine() == "yes")   
  5.     {  
  6.         field = 34;  
  7.     }  
  8.     // Just throw the exception  
  9.     throw new Exception();  
  10. catch when(fieldModified())   
  11. {  
  12.     // Log the errors, reverse the transaction etc.  
  13. }  
So instead of writing that condition inside, we can write that condition in front of that catch block itself. Technically, both were OK, only this way we are leaving most of the work to the compiler and we are designing the code to be more readable, read it like “try ... this code ... catch when field modified ... continue." This provides you with a simple way of reading the code. The IL get some branches around the catch block so that code can jump from one location to another and so on.

Remarks and references:

Technically, I won’t use this in any of my applications because I try to avoid transaction-like programming. But, if you are using transaction-like programming, such as SQL queries or bank management systems, I would recommend that you use these conditions on your catches. They can be of great use when you are logging errors in transactions. The function used would determine if there were changes (or what-ever you want to do in that function!) and if that condition is true, error would be caught, logged (if code is provided) and then re-thrown (if code is provided).
For more:
Nameof operator

Before saying anything at all, I want to confess that I have been one of those responders who said, you cannot have the name of the variable! The compiler doesn’t know the name of the variables, they are just labels. Well, not anymore. C# 6 provides you with another “amazing” feature that lets you get the actual name of the variable, not just the value of that variable.

Before C# 6, nameof operator was not present. With C# 6, this new feature can allow you to know the names of the variables, not just their values. So for example, previously we did:

Console.WriteLine($"Hello, my name is {Name}");

Now we can do this too,

Console.WriteLine($"Value of {nameof(Name)} variable is {Name}");

operator
                                    Figure 2: Use of nameof operator in real world.

However, the actual use cannot be determined here. The actual use of this would be when we want to know the variable names too. We could definitely (before C# 6) hardcode the names, but after modification, refactoring, they would be of no use anymore. However, now C# 6 can allow us to have the names of those variables too.

To understand the working, have a look at the MSIL generated:
  1. IL_0000: nop  
  2. IL_0001: ldstr "Value of {0} variable is {1}"  
  3. IL_0006: ldstr "Name"  
  4. IL_000B: ldarg.0  
  5. IL_000C: ldfld UserQuery.Name  
  6. IL_0011: call System.String.Format  
  7. IL_0016: call System.Console.WriteLine  
  8. IL_001B: nop  
  9. IL_001C: ret  
This shows, that the variable names are passed as string objects to the function and then the strings formatted (as we talked in the string interpolation), and finally the result is printed. So basically, all of this is just sugar-coating.

Null-conditional operator

For this feature too, I have been always very narrow-minded. I never liked it, perhaps because I have written a “good way to handle null exception” as:
  1. if (obj != null)  
  2. {  
  3.     // "Safe" code here  
  4. }  
  5.   
  6. // OR  
  7. try   
  8. {  
  9.     // Code here...  
  10. catch (NullReferenceException e)   
  11. {  
  12.     // Code here...  
  13. }  
But, things have changed. Previously, I was writing a library, in which I was supposed to get a list of objects from JSON data. So basically, if the source was empty or like “[]”, the array would be typically null. In other words, to overcome the exception, I would have to write something like this:
  1. // Deserialize the string  
  2. var list = JsonConvert.DeserializeObject<List<Type>>(jsonString);  
  3.   
  4. // Then check if it is null before returning  
  5. return (list == null) ? new List<Type>() : list;  
  6.   
  7. // Or using null-coalescing operator  
  8. return list ?? new List<Type>();  
However, as of C# 6 introduced something new, just to overcome the null exception in each line.
var item = list?[index]; // item would be null, if list is null

I am still not very much moved by this feature, because setting something to null based on null-ness of another is not a good idea. Is it? We can easily do this:
  1. // Get the list  
  2. var list = Model.GetList();  
  3. var item = new Item(); // Just assume it  
  4.   
  5. if (list != null && index < list.Count)  
  6. {  
  7.     item = list[index];  
  8. else   
  9. {  
  10.     // Show the error  
  11. }  
  12.   
  13. // In C# 6 we do  
  14. var list = Model.GetList();  
  15. var item = list ? [index];  
  16.   
  17. if (item == null)   
  18. {  
  19.     // Show the error  
  20. }  
Now basically, following this approach, we have “easily” removed on conditional block. But still, our code is exposed to:
  1. Null reference exception: We still need to check the item for this, or continue to use the same steps to avoid null reference exception along the track, and finally, tell the client, “Oooooops! There was a problem!”

  2. Index out of range: In the previous code, we would check the index too, however to do that, we would require a new block in C# 6 code, and that would ultimately lead us to a state where null-conditional operator would lose its meaning.
So, have a look at this code:
  1. List<int> i = null;  
  2. var item = i?.First();  
  3. // Item would be null if list is null. But we managed to minimize errors "yay!"  
Technically, we know item is null. But just to check it, we generate the MSIL too,
  1. IL_0000: nop  
  2. IL_0001: ldnull  
  3. IL_0002: stloc.0 // i  
  4. IL_0003: ldloc.0 // i  
  5. IL_0004: brtrue.s IL_0011  
  6. IL_0006: ldloca.s 02  
  7. IL_0008: initobj System.Nullable<System.Int32>  
  8. IL_000E: ldloc.2  
  9. IL_000F: br.s IL_001C  
  10. IL_0011: ldloc.0 // i  
  11. IL_0012: call System.Linq.Enumerable.First  
  12. IL_0017: newobj System.Nullable<System.Int32>..ctor  
  13. IL_001C: stloc.1 // item  
  14. IL_001D: ret  
Look at IL_0017, what this does is, that it just creates a new instance of an integer of nullable type. So basically, what we have above is:

int? nullable = null; // Int is struct! That is why we append "?" to the type.

The MSIL for this case is:
  1. IL_0000: nop  
  2. IL_0001: ldloca.s 00 // nullable  
  3. IL_0003: initobj System.Nullable<System.Int32>  
  4. IL_0009: ret  
Gotcha! This is same as to what we had previously. Only difference is the syntax now. Nothing new. So we can also conclude that our item is of type “Nullable<int>“. We already had that, didn’t
we? :-)

Remarks and references:

This is (yet!) another sugar coating to C# compiler and the syntax. But I like it. However, there are still many things that you may want to learn before digging any deeper into the code.
Static, just got better!

Another new feature provided by C# 6 is the static keyword in the using statement. So basically, what we have got is a method to include the classes themselves, and not just the namespace packages. What this feature does is already very popular, so let me just continue to talk about what I had to talk about. I have a few things that I want to talk about … Starting with the first one:

First of all, when you write something like,

using static System.Console;

It doesn’t mean, that each time you call “WriteLine” (or other Console’s member functions), it would be the function of Console that gets called. This is more like ambiguity here. For example, the following code:
  1. using System;  
  2. using static System.Console;  
  3.   
  4. namespace CSTest  
  5. {  
  6.     class Program   
  7.     {  
  8.         static void Main(string[] args)   
  9.         {  
  10.             WriteLine("Love for all, hatred for none.");  
  11.             Read();  
  12.         }  
  13.   
  14.         public static void WriteLine(string message)   
  15.         {  
  16.             Console.WriteLine($ "'{message}' printed by member function.");  
  17.         }  
  18.     }  
  19. }  
The output of this programs is:

output
                            Figure 3: Output of the member function.

So basically, what we can conclude is that even though our Console class is introduced, but compiler prioritizes the member functions, the priority is done in the case of both being static. If your member function is instance, then the compiler would raise an error, so in that case you will always have to write the full name for the function with the type it is associated to. Like this:
  1. using System;  
  2. using static System.Console;  
  3. 7  
  4.   
  5. namespace CSTest  
  6. {  
  7.     class Program   
  8.     {  
  9.         static void Main(string[] args)   
  10.         {  
  11.             Console.WriteLine("Love for all, hatred for none.");  
  12.             Read();  
  13.         }  
  14.   
  15.         public void WriteLine(string message)   
  16.         {  
  17.             Console.WriteLine($ "'{message}' printed by member function.");  
  18.         }  
  19.     }  
  20. }  
This would now run the function from Console class object.

message
Figure 4: Message printed by Console.WriteLine function.

This just executes the function. There is another thing that I want to discuss, the static include is not just for the built-in classes, you can use them in your cases and your class objects too. Just for the sake of example, I have created a sample class that would allow us to use the functions in a similar behavior.
  1. class Sample  
  2. {  
  3.     public static void StaticFunction() {}  
  4.     public void InstanceFunction() {}  
  5. }  
  6.   
  7. // Adding a struct would also work. Static functions would be pulled.  
  8. struct SSample   
  9. {  
  10.     public static void StructStaticFunction() {}  
  11. }  
Now, I don’t want to demonstrate the use of struct or class. So, now you can call those functions in your own class as if you were calling them from within the class itself.

Remarks and references:

This works for structs and as well as classes. The thing is that this works with the functions who are:
  1. Public, private functions are not shown (of course!)
  2. Static, instance functions require an instance, so compiler doesn’t bother showing them at all.
Static classes are all static, their members are also meant to be static so every member function of a static class would be accessible. However, in case of instance classes, only static functions are visible in the list of IntelliSense.
For more information, please read:
Auto-properties, and their improvements

Auto-properties have been available in C# for a long time by now, the thing is that they now introduce a new feature. “Initializers” can be used to initialize these properties to their defaults. A few of the ways that they can be used is like this:
  1. private string Name  
  2. {  
  3.     get;  
  4.     set;  
  5. } = "Afzaal Ahmad Zeeshan";  
  6.   
  7. // Without a setter, a readonly  
  8. private string Name   
  9. {  
  10.     get;  
  11. } = "Afzaal Ahmad Zeeshan";  
  12.   
  13. // Simply read-only  
  14. private readonly string Name = "Afzaal Ahmad Zeeshan";  
But remember, the last one is a field, not a property. For example, see this:
  1. private string Property  
  2. {  
  3.     get;  
  4.     set;  
  5. } = "Afzaal Ahmad Zeeshan";  
  6.   
  7. private string getterOnlyProperty   
  8. {  
  9.     get;  
  10. } = "Afzaal Ahmad Zeeshan";  
  11.   
  12. private readonly string readonlyField = "Afzaal Ahmad Zeeshan";  
This would be translated as:
  1. IL_0000: nop  
  2. IL_0001: ret  
get_Property:
  1. IL_0000: ldarg.0  
  2. IL_0001: ldfld UserQuery.<Property>k__BackingField  
  3. IL_0006: ret  
set_Property:
  1. IL_0000: ldarg.0  
  2. IL_0001: ldarg.1  
  3. IL_0002: stfld UserQuery.<Property>k__BackingField  
  4. IL_0007: ret  
  5.   
  6. // getterOnlyProperty is a getter-only, so not set_ field is available.  
  7. get_getterOnlyProperty:  
  8. IL_0000: ldarg.0  
  9. IL_0001: ldfld UserQuery.<getterOnlyProperty>k__BackingField  
  10. IL_0006: ret  
The code is categorized under getters and setters for the properties, and the readonly field is just a variable in the program.

Remarks and references:

The new thing introduced in C# 6 is that you can now set the values to a default, in previous versions you would have to enter a new value in the constructor. However, now you can enter that value right there!

For more please read:
  1. Accessors in C# on MSDN.
Lambdas have evolved

If you have ever read my previous posts, you may have known that I am a huge fan of lambda expressions of C#, especially when it comes to handling the events. I have always enjoyed programming, based on these lambdas.
What now can be done is that lambda expressions can be used now to create the functions too (just like before), not just that. They can be used to simplify the getter-only properties too.
The syntax, cannot show you how simple it gets. For example, the following code block,

public int Multiply (int a, int b) { return a * b; }

It looks very much simple, and is optimized. However, the MSIL code looks “horrible”.

Multiply:
  1. IL_0000: nop  
  2. IL_0001: ldarg.1  
  3. IL_0002: ldarg.2  
  4. IL_0003: mul  
  5. IL_0004: stloc.0  
  6. IL_0005: br.s IL_0007  
  7. IL_0007: ldloc.0  
  8. IL_0008: ret  
This is a very long MSIL, which would be translated and would require a lot of CPU cycles. While on the other hand, if you can see this code:

public int Multiply (int a, int b) => a * b;

This lambda expression does same, as what the previous one did. But, is very much performance-efficient. The MSIL generated with this code is like this:

Multiply:
  1. IL_0000: ldarg.1  
  2. IL_0001: ldarg.2  
  3. IL_0002: mul  
  4. IL_0003: ret  
How small MSIL code, right? So this demonstrates that using a lambda expression to write our function, we cannot just simplify the code size, we can also fine-tune the code that is executed for that.

Another major use of these lambdas is while creating getter-only fields. Now, their topic is already discussed above. But, however, I would like to talk about them again…

public double PI { get; } = 3.14;

The MSIL generated for this would be (you guessed it right!) a get property, and a backing up field. Like this:

get_PI:
  1. IL_0000: ldarg.0  
  2. IL_0001: ldfld UserQuery.<PI>k__BackingField  
  3. IL_0006: ret  
So basically, what we have is a block that returns the value of the field that is backing up this property; whenever we call the property. Now, to fine tune it using C# 6, what we can do is something like this:

public double PI => 3.14;

The MSIL for this is really very amazing, just the way we improved the function, we can improve this field too, increasing the access time. So now the MSIL is:

get_PI:
  1. IL_0000: ldc.r8 1F 85 EB 51 B8 1E 09 40  
  2. IL_0009: ret  
Pretty much amazing, and short! It just pushes this content, as float, on the stack. Then calls the return to provide the value. The thing is that we don’t need a backing field at all. To make it more readable, please read this:

public string PI => "Afzaal Ahmad Zeeshan";

Now, in the case of a field-backed-property, the value would be stored in the backing field and when we would call this, the backing field would be called (a new call!) and then that value would be returned. However, in this case, what happens is something like this:

get_PI:
  1. IL_0000: ldstr "Afzaal Ahmad Zeeshan"  
  2. IL_0005: ret  
Simply, this would load the string on the stack, and would then return this value. It is more like having that constant field in your project that gets places wherever it is called from and so on.

Remarks and references:

Lambda expressions are definitely very useful, not in just decreasing the syntax size, but also in making the source code size small, too. The lambdas are inherited from “Functional programming”, and well, in the world on object-oriented programming they have seriously marked their place.

For more please read:
Points of Interest

In this post, I have talked about the most “popular” and interesting features that C# 6 has introduced to its users. However, until now most of the time I have only seen the “same song and dance." Programmers have just talked about the fuss, no one talked about their internal implementation.

In this post, I have shown what difference they have, how they differ, what syntactic sugars are and which really do have an influence on your programs. Basically, from this list, my favorites are:
  1. String interpolation
  2. Lambda expressions
Others are useful, yet I don’t feel like using them in my own projects. If you have anything else on your mind, that I don’t yet know… Please share it with me. :-) I would love to hear.


Recommended Free Ebook
Similar Articles