Understanding C# 10.0 Features with some code examples

1. Start with a project using Visual Studio 2022 Preview since it supports .Net 6.0 Preview:


2. I edit my project file  to use C#10.0 and build is successful too:


3. One of the first features I try is global usings. So, added a file will all the global namespaces I wish to use across files in the project and gave it a random name - globalusings.cs. Since System.Collections.Generic is a good namespace to use globally, I add it with the global keyword  under other usings I had copied over, I received this message:

"A global using directive must precede all non-global using directives"


4. I moved the concerned global using line to the top and then went onto a file to use a List<string>. The list is not only recognized but also gets tab auto-complete option! 


Remove the langversion directive in the project file and, you should get the following error -
"Feature 'global using directive' is not available in C# 8.0. Please use language version 10.0 or greater."



Hence proven that Global usings is one of the features of C# 10.0!

Another interesting feature I noticed was the the new keyword without specifying the default constructor name while you instantiate a class. Although this is available from C# 9.0, its good that I found now!

I switched over the langVersion to an earlier version in the project file and I got this syntax error:

"Feature 'target-typed object creation' is not available in C# 8.0. Please use language version 9.0 or greater."


So, with C# 9.0 and above you can save some keystrokes by invoking a default constructor this way:

SampleClass sampleClass= new();

instead of

SampleClass sampleClass= new SampleClass();



The file-scoped namespace definition didn't work as expected and, I raised a ticket and waiting to understand it better - 


But, the above feature has a pretty interesting take on reducing horizontal screen estate. It comes in place in order to get rid of tabs we normally use to add class and methods within a namespace. The current take is, if we get rid of the horizontal real estate, we can save a lot of space in so many files across source repos over the web!

So, I'm not sure how people who are particular about aesthetics like tabbing, spaces in code lines will feel about this!

Anyway, let's jump over to the next interesting feature -

Extended Property Pattern Matching

This seems to be a popular feature in other languages like Kotlin and seems to have made its way into C# recently.  I tried this feature with an example. You need a nested property to understand this. So, I created a Fruit class and ensured Orange and Apple inherit from Fruit as follows. For the sake of this example, I assumed that -

a. Skin color for apple is hybrid - in my mind, it could have a tinge of yellow along with red! So, its mixed color
b. Skin color for Orange fruit is always orange so, its single color

This is the core logic:
FruitNS.cs

namespace FruitNS 
{
    public class Fruit //my base class
    {        
        public Color SkinColor { get; set; }

        public string GetSkinColor(bool hybridcolorflag)
        {
           if (hybridcolorflag) return "Mixed Color";

            return "Single Color";
        }
    }

    public class Color  //this is the class that supports property nesting
    {
        public bool Hybrid { get; set; } //this is our nested property
    }

    class Orange : Fruit { } //my child class - 1

    class Apple : Fruit { }  //my child class - 2

    public class FruitColorLogic
    {
        public string Classify(Fruit fruit) => fruit switch
        {
            { SkinColor.Hybrid:false } => fruit.GetSkinColor(false),
            { SkinColor.Hybrid: true } => fruit.GetSkinColor(true)
        };
    }
}

This is my intermediate invoker:

MyFruitInvokerNS.cs

namespace MyFruitInvokerNS { }; //note how namespace need not be nesting the class below

class MyFruitClass //didn't provide  any access specifier but this was picked from the calling class
{    
    public string MyFruitColorInvokerMethod(Fruit fruit)
    {   
        FruitColorLogic fruitColorLogic = new();//saving some keystrokes here with just new()
        return fruitColorLogic.Classify(fruit);
    }
}

This is my client: 

Program.cs

using FruitNS;

namespace MyCSharpTest
{
    class Program
    {
        static void Main(string[] args)
        {           
            MyFruitClass myFruitClass= new();

            Orange orange = new();
            orange.SkinColor = new Color
            {
                Hybrid = false
            };

            string myFirstFruitColorType=myFruitClass.MyFruitColorInvokerMethod(orange);

            Apple apple = new();
            apple.SkinColor = new Color
            {
                Hybrid = true
            };

            string mySecondFruitColorType = myFruitClass.MyFruitColorInvokerMethod(apple);
        }
    }

}

Without beating around the bush, the highlighted syntax is the new addition in C# 10.0! If I change my langVersion to 9.0, I get the following error -

"Feature extended property patterns is not available in C# 9.0. Please use language version 10.0 or greater"



Because, before C# 10.0, those lines must look as follows!

{ SkinColor: { Hybrid: false } } => fruit.GetSkinColor(false),
{ SkinColor: { Hybrid: true } } => fruit.GetSkinColor(true)

In other words, you can access a nested property only with braces prior to C# 10.0{ Parentproperty: { Childproperty: pattern } }

When I execute the code

1. The invoker is called from the client program:


2. Core logic fires using the nested property syntax:


3. Actual logic for orange is picked:



4. Flow back to client:


5. Similarly, my second fruit color is picked and proven as a mixed color one!

Comments

Popular Posts