In-Depth

A Sharper, More Powerful C# 6.0

The newest version of C# 6.0 that you'll see in Visual Studio 2015 improves and streamlines the way you'll code for a "mobile first, cloud first" world.

C# 6.0 will soon be the latest released version of Microsoft's proprietary language that you'll see with the upcoming Visual Studio 2015 and the .Net Framework 5.0 releases. Like all new product releases coming from Microsoft, the goal is to improve coding tasks and make the code more streamlined.

Since Visual Studio 2015 has not been released to market as of the time of this writing (release is on July 20), I will be using VS 2015 RC to demonstrate the new features in the language. Please keep in mind that features are subject to change with the RTM version. For the demo, I will be using a Windows Application with a button for every feature (see Figure 1).

UI of Demo Application
[Click on image for larger view.] Figure 1: UI of Demo Application

In this article, I'll show off these new language features:

  • nameof
  • String interpolation
  • Exception filters
  • Index initializers
  • Null-conditional operators

The nameof() expression is used to retrieve the name of the variable. An example of this can be seen in Listing 1 and you can see it demonstrated in the btnNameOf_Click() of the demo.

Listing 1: Example of nameof()

        private void btnNameOf_Click(object sender, EventArgs e)
        {
            string myString = null;

            if (myString == null)
                tbOutput.Text += "The value of the variable " + nameof(myString) + " is NULL";
        }

This can be useful when logging errors to capture the name of a specific field. Prior to this, there was no easy way to accomplish this task. Developers had to leverage Expression Trees in several lines of code. Now it's a simple method call.

String Interpolation
String interpolation has been facilitated in the past using the String.Format() method. This utilized numbered place holders in the String.Format() and required aligning them with the correct variables. This has been used in C# since version 1.1, but in C# 6 this functionality gets streamlined. Now, developers can use the '$' escape character and embed the variable names directly within the string inside curly braces. An example of this can be seen in Listing 2.

Listing 2: Example of String Interpolation

        private void btnStrInt_Click(object sender, EventArgs e)
        {
            string carModel = "Mustang";
            int numColors = 11;

            //Old Way
            string Old = String.Format("The {0} is available in {1} colors{{s}} ", carModel, numColors.ToString());
            
            //New Ways            
            string s1 = $"{carModel} is available in {numColors} colors "; 
            string s2 = $"{carModel, 100} is available in {numColors} colors";
            string s3 = $"{carModel} is available in {numColors} color{(numColors >= 2 ? "s" : "")} ";

            tbOutput.Text += s1 + "\r\n" + s2 + "\r\n" + s3;
        }

Notice how the string variables are defined in the Old Way section vs. the New Ways section. A '$' initiates the escape sequence for the entire string, allowing multiple insertions of variable names within {}. Visual Studio 2015 highlights the syntax coloring where {Name} and {Age} are in black, but other string literals are in red.

The string interpolation also allows for string formatting within {}. Variable s2 is defined with {Name, 100}, causing the name to be right-justified in a space-padded field of 100 characters. Variable s3 uses the {} for an embedded expression, making "year" plural if Age > 2.

Exception Filters
The concept of Exception Filters is another new feature coming in C#6. This allows an exception to be caught in the CATCH block only a specified condition is met when the exception is thrown. Looking at Listing 3, the CATCH blocks now have a WHEN clause. This will check if the specified filter condition is true when the exception is thrown. If so, the CATCH block will be executed otherwise, it will be skipped.

As with all exception handling, if a CATCH block does not catch that exception (either because of the exception type of the filter condition), an unhandled exception is thrown in the program. Also, the FINALLY block always executes, regardless of the exception thrown.

Listing 3: Example of Exception Filters

        private void btnExFilter_Click(object sender, EventArgs e)
        {
            string UserCode = "1122";

            try
            {
                throw new Exception("User Error");
            }

            catch (Exception ex) when (UserCode == "1122")  
            {
                tbOutput.Text += "Exception caught for UserCode 1122 \r\n";
            }

            catch (Exception ex) when (UserCode == "1234")
            {
                tbOutput.Text += "Exception caught for UserCode 1234 \r\n";
            }

            catch (Exception ex)
            {
                tbOutput.Text += "General Exception caught for a misc UserCode \r\n";
            }

            finally
            {
                tbOutput.Text += "Executing FINALLY block \r\n";
            }
        }

Index Initializers
Aside from new keywords, C# 6 has been modified to encourage more streamlined coding. Index Initializers is one such example. The example in Listing 4 shows the old way and new way of initializing a dictionary object.

Listing 4: Example of Index Initializers

        private void btnIndexInit_Click(object sender, EventArgs e)
        {
            // Old way of initializing dictionary objects
            Dictionary<int, string> oldRomanNumerals = new Dictionary<int, string>()
            {
                { 1, "I" },
                { 2, "II" },
                { 3, "III" },
            };

            //New way of initializing dictionary objects
            Dictionary<int, string> newRomanNumerals = new Dictionary<int, string> ()
            {                
                [1] = "I",
                [2] = "II",
                [3] = "III"
            };

            tbOutput.Text += "Roman Numeral 1=" + newRomanNumerals[1] + "\r\n";
            tbOutput.Text += "Roman Numeral 2=" + newRomanNumerals[2] + "\r\n";
            tbOutput.Text += "Roman Numeral 3=" + newRomanNumerals[3] + "\r\n";
        } 

Both old and new ways listed are still valid syntax in C#6, but the new method is certainly more streamlined.

Null-Conditional Operators
Another feature for streamlining code is the Null-conditional Operator. Many times before accessing an object, a null check needs to be performed to prevent the application from throwing a Null Exception. Typically this is done with an IF-Then statement. When trying to access elements several levels deep into an object, the IF-Then structure can be relatively lengthy for accessing one member (see Listing 5).

Listing 5: Traditional Way of Checking Null Objects/Members

            Car[] cars = new Car[2];
            string car1Make;

            //Old Way
            if (cars != null)
            {
                if (cars[1] == null)
                    car1Make = null;
                else
                    car1Make = cars[1].Make;
            }

The new Null-conditional operator streamlines the Null checking code significantly. By using the new operator '?', it will automatically return a NULL if the object is Null or the value of the member if it's not null. This all occurs in a single in-line statement. Listing 6 shows this new operator in action.

Listing 6: Example of Null-conditional operator

            string carModel = cars[1]?.Model.ToString();  //returns NULL
            tbOutput.Text += "The Car Model name is [" + carModel + "]";

            string carMake = cars[1].Make?.ToString();   //throws NullReference Exception  

Notice the placement of the '?' operator. When setting the variable carModel, the operator is used prior to accessing the Model member variable. This ensures a NULL is returned if the cars[1] object is null, or the model of the given object.

On the other hand, if the '?' operator is used on a member of a Null object, it throws a Null Reference Exception. This is demonstrated in the last line of Listing 6. The key thing to remember is to use '?' at the highest level of object access to avoid Null Reference Exceptions.

C# has quickly gained wide acceptance since its inception in 2000 with the release of .Net Framework 1.0. Now with the sixth major release on the horizon, C# offers new features to increase developer productivity while making code more streamlined. Some may refer to these features as syntactical sugar. Whatever you call it, C# 6 will make for a better coding experience while continuing to gain more popularity among developers.

About the Author

Sam Nasr has been a software developer since 1995, focusing mostly on Microsoft technologies. Having achieved multiple certifications from Microsoft (MCAD, MCTS(MOSS), and MCT), Sam develops, teaches, and tours the country to present various topics in .Net Framework. He is also actively involved with the Cleveland C#/VB.Net User Group, where he has been the group leader since 2003. In addition, he also started the Cleveland WPF Users Group in June 2009, and the Cleveland .Net Study Group in August 2009, and is the INETA mentor for Ohio. When not coding, Sam loves spending time with his family and friends or volunteering at his local church. He can be reached by email at [email protected].

comments powered by Disqus

Featured

Subscribe on YouTube