Pages

C# Features Through the History - Version 10

 

The main features of version 10!


Version 10 C# came together with the breakthrough caused by .NET 6, in the year 2021. This is the stable version of the framework, going beyond on the idea of unified platform:

-----------------------------------------------------

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! 




-----------------------------------------------------


Global using Directives

The global using directive is one of the factors that is coming to help turning the codebase cleaner. You can define the using namespaces in a single place (an external .cs file, for example). Here are few examples on how you can use it:
 
namespace CSharpStudy.CSharp10
{
    public class GlobalUsings
    {
        public static void ExecuteExample()
        {
            WriteLine("Hi");
            SYS.Console.WriteLine("Hi");

            var x = TextReader.Null;
        }
    }
}              
              
You can either include or remove usings directly into .csproj, with the using directive:
 


  
 
File-Scoped Namespace

One more syntactic sugar that will help us to define in a clearer and simpler way the namespaces:
    
namespace CSharpStudy.CSharp10;

public class FileScopedNamespace
{
    public static void ExecuteExample()
    {
        WriteLine("asd");
    }
}                   
                                  
 
 
Extended Property Patterns

With extended property patterns it is possible to access internal elements of an object in an easier way:

namespace CSharpStudy.CSharp10;

public class ExtendedPropertyPatterns
{
    public static void ExecuteExample()
    {
        var pet = new Pet
        {
            Name = "Jimmy",
            Age = 10,
            Owner = new PetOwner
            {
                Name = "James",
                Age = 22
            }
        };

        object obj = pet;
        // old way: if (obj is Pet { Owner: { Name: "James" } })
        // now, in a simplified way:
        if (obj is Pet { Owner.Name: "James" })
            WriteLine("Jame's pet");

        // same idea, now in a switch clause
        var isOwnerOliverOrJames = pet switch
        {
            { Owner.Name: "Oliver" }
              or { Owner.Name: "James" } => true,
            _ => false
        };
    }
}

internal class Pet
{
    public string Name { get; set; }
    public int Age { get; set; }
    public PetOwner Owner { get; set; }
}

internal class PetOwner
{
    public string Name { get; set; }
    public int Age { get; set; }
}                  
                  

 
Constant Interpolation String

Simple and self-explained feature:
                        
        const string message = "Fixed message";
        
        const string constantWithInterpolationString = $"Now it's possible doing this with const: {message}";                    
	
 
 
Record Structs

Now it is possible to declare a record struct or a readonly record struct:
    
    internal record struct Message
    {
        public int Type { get; set; }
        public string Value { get; set; }
    }

    internal readonly record struct StrictMessage
    {
        // Error (cannot have set):
        //public int Type { get; set; }
        public int Type { get; }
        public string Value { get; }
    }        
     
 
 
Lambda Improvements
One of the improvements regarding lambdas is the support in some case for automatically inference of the type of the lambda expression: 
Sometimes the compiler just doesn't have information enough to solve the natural type (and that can be solved helping the compiler with the desired expected data type): : 	
                        
        // var parseError = s => int.Parse(s); // error: the delegade type could not be inferred

        // var choose = (bool b) => b ? 1 : "two"; // ERROR: Can't infer return type       
        
        var chooseOk = object (bool b) => b ? 1 : "two"; // Correctly solved            
            
 
 
ArgumentNullException
Now there is an improvement in the way we throw an ArgumentNullException:
                        
        object message = null;

        // old-way:
        if (message == null)
            throw new ArgumentNullException(nameof(message));

        // refactory old-way:
        var x = message ?? throw new ArgumentNullException(nameof(message));

        // C# 9.0 way:
        if (message is null)
            throw new ArgumentNullException(nameof(message));
        
        // C# 10 way:
        ArgumentNullException.ThrowIfNull(nameof(message));                
                    
	
 -----------------------------------------

Fabio Ono

No comments:

Post a Comment