Pages

C# Features Through the History - Versions 7.1, 7.2 and 7.3

 

The main features of versions 7.1, 7.2, and 7.3, available for you now!


Between the years of 2017 and 2018, after the big change provided by the C# language, following the .NET Core 2.0 framework, new interesting changes were added.  

How to use the examples 

The examples are available here. You can open the solution and play around. Just uncomment the code and have fun! 



C# 7.1 Features

Async Main

Now, it's possible to handle async routines directly from the method main. It means that you can write some code that returns a Task. These are the possible constructions for the method main: 
static async Task Main(string[] args)
static async Task Main()
static async Task<objectMain()
static async Task<objectMain(string[] args)

Default Literal Expressions

The default literal expressions provide a way to initialize a variable to the default value. What this  version of the language provided was a shorter way to use this feature:
    public static class DefaultLiteralExpressions
    {
        public static void ExecuteExample()
        {
            var value1 = default(int); // old implementation for default value expressions
            int value2 = default;      // new implementation for default value expressions
            Console.WriteLine(SumValues(value1, value2));
            
            Console.WriteLine(SumValues());
        }

        //defining a method with the default expression, so it can be executed withoud passing parameters
        private static int SumValues(int val1 = default(int), int val2 = default) => val1 + val2;
    }
 
Inferred Tuple Names

This is a minor change but can help when working with tuples. Now, it's possible to infer the tuple identifier implicitly, just passing the variable as parameters:
            var name = "John";
            var age = 20;

            // define the tuple in an explicitly way 
            var tuple1 = (Name: name, Age: age);
            Console.WriteLine(tuple1.Name, tuple1.Age);

            // define the tuple in an implicitly way
            var tuple2 = (name, age);
            Console.WriteLine(tuple2.name, tuple2.age);

Generic Pattern Matching

Generic With pattern matching is possible to control the flow based on a generic type:
        public static void ExecuteExample()
        {
            var person = new Person { Age = 20 };
            Print(person);
        }

        // now, it's possible to evaluate generic types via pattern matching
        private static void Print(T type) where T : Person
        {
            switch (type)
            {
                case null:
                    break;
                case Person person:
                    Console.WriteLine(person.Age);
                    break;
            }
        }

        class Person
        {
            public int Age { get; set; }
        }


C# 7.2 Features

Non-Trailing Named Arguments

Now named arguments can be followed by positional arguments, without breaking the code:
        public static void ExecuteExample()
        {
            // if the order is ok, you can send a un
            Print("message", name: "John", 10);
        }

        private static void Print(string message, string name, int age)
        {
            Console.WriteLine($"Message: {message} - Name: {name} - Age: {age}.");
        }
			  
Private Protected Access Modifier

This access modifier enables access for derived classes in the same assembly:
        public static void ExecuteExample()
        {
            var person = new Person { 
                Name = "James", 
                //Age = 20 //'PrivateProtected.Person.Age' is inaccessible due to its protection level
            };

            var person2 = new Person2
            {
                Name = "Josh",
            };
            person2.MyAge = 12; //accessible 
        }

        private class Person
        {
            public string Name { get; set; }
            private protected int Age { get; set; }
        }

        private class Person2 : Person
        {
            public int MyAge
            {
                get { return Age; } //property accessible
                set { Age = value; }
            }
        }
			  
Conditional ref Expressions

The result provided by a conditional expression can be a reference:
            var array1 = new int[] { 1, 3, 5, 7, 9 };
            var array2 = new int[] { 1, 3, 5, 7, 9 };

            ref var ret = ref (array1 != null ? ref array1[0] : ref array2[0]);
		  
		  
C# 7.3 Features

This version focused especially on performance improvements for safe code and general improvements for existing features:

  • It's possible to access fixed fields without pinning.
  • Use additional generic constraints.
  • Use fixed statements of any type that supports a pattern.
  • Using initializers on stackalloc arrays.
  • Possibility of reassign ref local variables.
  • Possibility to evaluate == and != with tuple types.
  • Method resolution when arguments differ by in has been improved.
  • Overload resolution now has fewer ambiguous cases.
  • Attach attributes to the backing field of auto-implemented properties.
  • Use expression variables in more locations.
      
---------------------------------------

I hope you have enjoyed this journey now. Have a nice week!

Here is the entire list of this series:

Fabio Ono

No comments:

Post a Comment