.NET 6,C# 10, ASP.NET Core and another style of programming

Cezary Walenciuk

.NET 6,C# 10, ASP.NET Core
and another style of programming

@walenciukC

Speaker
What is new ?
🤔
CW
Copyright © 2021 Cezary Walenciuk
CW
Copyright © 2021 Cezary Walenciuk

BenchmarkRunner

                    
                        class Program
                        {
                            static void Main(string[] args)
                            {
                                var results = BenchmarkRunner.Run<IsEvenBenchmark>();
                                Console.ReadKey();
                            }
                        }
                        
                        [MemoryDiagnoser]
                        [SimpleJob(RuntimeMoniker.Net60)]
                        [SimpleJob(RuntimeMoniker.Net472)]
                        public class IsEvenBenchmark
                        {
                            [Benchmark]
                            [Arguments(42)]
                            public bool IsEven(int i)
                            {
                                return i % 2 == 0;
                            }
                        }
                    
                
CW
Copyright © 2021 Cezary Walenciuk
CW
Copyright © 2021 Cezary Walenciuk
New classes and methods in .NET 6

ArgumentNullException Old code

                    
                        void Example1(string id)
                        {
                            if (id is null)
                            {
                                throw new ArgumentNullException(nameof(id));
                            }
                        }
                    
                

ArgumentNullException.ThrowIfNull

                    
                        void Example2(string id)
                        {
                            ArgumentNullException.ThrowIfNull(id);
                        }
                    
                

ProcessId and ProcessPath in .NET 2-5

                    
                        Process process  = Process.GetCurrentProcess();

                        string path = process.MainModule.FileName;
                        int id = process.Id;

                        Console.WriteLine(path);
                        Console.WriteLine(id);
                    
                

ProcessId and ProcessPath in .NET 6

                    
                        string path2 = Environment.ProcessPath;
                        int id2 = Environment.ProcessId;
                    
                

Cryptographically Secure Pseudorandom Number Generator (CSPNG)

                    
                        using System.Security.Cryptography;
                        
                        //for
                        //- key generation
                        //- nonces
                        //- salts in certain signature schemes
                        var random = RandomNumberGenerator.
                            GetInt32(1, 1000000);

                        var bytes = RandomNumberGenerator.
                            GetBytes(255);
                    
                

Waits for the next tick of the timer or for the timer to be stopped

                    
                        using PeriodicTimer timer = 
                            new(TimeSpan.FromSeconds(2));

                        while (await timer.WaitForNextTickAsync())
                        {
                            Console.WriteLine(DateTime.UtcNow.Second);
                        }
                        
                    
                

NativeMemory

                    
                        unsafe
                        {
                            byte* buffer = (byte*)NativeMemory.Alloc(255);
                            NativeMemory.Free(buffer);
                        }
                    
                
PriorityQueue

Waits for the next tick of the timer or for the timer to be stopped

                    
                        PriorityQueue queue = new PriorityQueue();

                        queue.Enqueue("A", 0);
                        queue.Enqueue("B", 3);
                        queue.Enqueue("C", 2);
                        queue.Enqueue("D", 1);

                        while (queue.TryDequeue(out string item, out int priority))
                        {
                            Console.WriteLine($"Popped Item : {item}. " +
                                $"Priority Was : {priority}");
                        }
                    
                
CW
Copyright © 2021 Cezary Walenciuk

Waits for the next tick of the timer or for the timer to be stopped

                    
                        PriorityQueue<string, int> queue = new PriorityQueue<string, int>();

                        queue.Enqueue("A", 0);
                        queue.Enqueue("B", 3);
                        queue.Enqueue("C", 2);
                        queue.Enqueue("D", 1);
                        queue.Enqueue("E", 0);
                        queue.Enqueue("F", 1);
                        
                        while (queue.TryDequeue(out string item, out int priority))
                        {
                            Console.WriteLine($"Popped Item : {item}. " +
                                $"Priority Was : {priority}");
                        }
                    
                
CW
Copyright © 2021 Cezary Walenciuk

DateOnly and TimeOnly

                    
                        var dateOnly = new DateOnly
                            (2021, 8, 20);
                    
                        var timeOnly = new TimeOnly
                            (08, 43, 57);
                    
                        DateTime dateTime = dateOnly.
                            ToDateTime(timeOnly);
                    
                

BitOperations

                    
                        uint number = 235;

                        if (!BitOperations.IsPow2(235))
                        {
                            number = 
                            BitOperations.RoundUpToPowerOf2(number);
                        }
                        
                        Console.WriteLine(number);
                    
                

Method EnsureCapacity

                    

                        var numbers = new List<int> { 1, 2 };
                        Console.WriteLine(numbers.Capacity < 100);
                        
                        numbers.EnsureCapacity(100);
                        
                        Console.WriteLine(numbers.Count == 2);
                        Console.WriteLine(numbers.Capacity == 100);
                        
                        numbers.EnsureCapacity(50);
                        Console.WriteLine(numbers.Capacity == 100);
                        
                        for (int i = numbers.Count; i < 100; i++)
                        {
                            numbers.Add(i);
                        }
                        
                        Console.WriteLine(numbers.Count == 100);
                        Console.WriteLine(numbers.Capacity == 100);
                    
                

list.Chunk

                    
                        var list = Enumerable.Range(1, 100);

                        foreach (var chunk in list.Chunk(10))
                        {
                            Console.WriteLine("This next chunk");
                            foreach (var item in chunk)
                            {
                                Console.WriteLine(item);
                            }
                        }
                    
                
What new in LINQ ?
MaxBy,MinBy, DistinctBy,UnionBy,IntersectBy,
ExceptBy

MaxBy i MinBy

                    

                        var products1 = new[] {
                            (Name: "Q", Price: 17),
                            (Name: "W", Price: 100),
                            (Name: "E", Price: 70),
                            (Name: "Y", Price: 17),
                         };
                         var products2 = new[] {
                            (Name: "R", Price: 17),
                            (Name: "T", Price: 12), };
                         
                         var b1 = products1.MaxBy(p => p.Price)
                             .Name == "W";
                         var b2 = products1.MinBy(p => p.Price)
                             .Name == "Q";
                    
                
TryGetNonEnumeratedCount

TryGetNonEnumeratedCount

                    
                        IEnumerable<int> seq1 = new[] { 0, 1, 2, 3, 4 };

                        seq1.TryGetNonEnumeratedCount(out int count1);
                        Console.WriteLine(count1 == 5);
                        
                        IEnumerable<int> seq2 = new
                            BetterCollectionBeacuseItsMine
                            <int>();
                        
                        var result =
                            seq2.TryGetNonEnumeratedCount(out int count2);
                        Console.WriteLine(result);
                    
                

FirstOrDefault with default

                    
                        var arr2 = new[] { 0, 2, 4, 6, 8, 10 };

                        var c1 = arr2.FirstOrDefault
                            (x => x > 11) == 0;
                        
                        var c2 = arr2.FirstOrDefault
                            (x => x > 11, -1) == -1;
                    
                

LINQ supports RANGE

                    
                        var arr = new[] { 0, 1, 2, 3, 4, 5 };

                        var a1 = arr.ElementAt(^2) == 4;
                        
                        var a2 = arr.ElementAtOrDefault
                            (^10) == default;
                        
                        var a3 = arr.Take(^2..).
                            SequenceEqual(new[] { 4, 5 });
                    
                
What new in async ?

WaitAsync

                    
                        await ExampleAsync();
                        Console.Read();
                        
                        static async Task<int> ExampleAsync()
                        {
                            var operation = SomeLongRunningOperationAsync();
                        
                            return await operation.WaitAsync
                                (TimeSpan.FromSeconds(3));
                        }
                        
                        static async Task<int> SomeLongRunningOperationAsync()
                        {
                            await Task.Delay(5000);
                            return 1;
                        }
                    
                

Parallel.ForEachAsync

                    
                        static async Task Example2Async()
                        {
                            var urlsToDownload = new[]
                            {
                                        "https://cezarywalenciuk.pl/",
                                        "https://twitter.com/WalenciukC",
                            };
                        
                            var client = new HttpClient();
                        
                            await Parallel.ForEachAsync(urlsToDownload,
                                async (url, token) =>
                                {
                                    var response = await client.GetAsync(url);
                        
                                    if (response.IsSuccessStatusCode)
                                    {
                                        Console.WriteLine
                                        (await response.Content.ReadAsStringAsync());
                                    }
                                });
                        }
                    
                
What new in
System.Text.Json ?
Write me in chat if you like
System.Text.Json ?
✍️

JsonPropertyOrder

                    

                        public class Game
                        {
                            [JsonPropertyOrder(1)]
                            public int Year { get; set; }
                        
                            public string Name { get; set; } // 0
                        
                            //serialize after Year
                            [JsonPropertyOrder(2)] 
                            public string Company { get; set; }
                        
                            // serialize before other properties
                            [JsonPropertyOrder(-1)] 
                            public int Id { get; set; }
                        }
                    
                

JsonPropertyOrder

                    
                        Game game = new()
                        {
                            Company = "Konami",
                            Name = "Silent Hill",
                            Id = 564,
                            Year = 1999
                        };

                        JsonSerializerOptions options =
                            new () { WriteIndented = true};

                        string json = JsonSerializer
                        .Serialize(game,options);

                        Console.WriteLine(json);
                    
                
CW
Copyright © 2021 Cezary Walenciuk
JsonNode,JsonObject,JNode

JsonNode and jNode

                    
                        JsonNode jNode = JsonNode.Parse
                        ("{\"array\":[1,6,7],\"name\":\"Cezary\"}");
                                
                        string name = (string)jNode["name"];
                        Console.WriteLine(name);
                                
                        string name1 = jNode["name"]
                        .GetValue<string>();
                                
                        int number = jNode["array"][2]
                        .GetValue<int>();
                    
                

JsonObject

                    
                        var jObject = new JsonObject()
                        {
                            ["name"] = "Konrad",
                            ["array"] = new JsonArray(2, 3, 4, 5)
                        };
            
                        string json = jObject.ToJsonString();
                        Console.WriteLine(json);
                    
                

IJsonOnDeserialized, IJsonOnDeserializing, IJsonOnSerializing, IJsonOnSerialized

                    
                        public class TShirt : IJsonOnDeserialized, 
                        IJsonOnDeserializing,
                        IJsonOnSerializing,
                        IJsonOnSerialized
                        {
                            public void OnDeserialized()
                            { }
                        
                            public void OnDeserializing()
                            { Validate(); }
                        
                            public void OnSerialized()
                            { }
                            public void OnSerializing()
                            { Validate(); }
                        
                            public string Color { get; set; }
                            private void Validate()
                            {
                                if (Color is null)
                                    throw new InvalidOperationException
                                        ($"{nameof(Color)} Can not be null");
                            }
                        }
                    
                
NET 6, System.Text.Json supports 'IAsyncEnumerable'

NET 6, System.Text.Json supports 'IAsyncEnumerable'

                    
                        public static async IAsyncEnumerable<int> 
                            GetNumbersAsync()
                        {
                            for (int i = 0; i < 5; i++)
                            {
                                await Task.Delay(2000);
                                yield return i;
                            }
                        }
                    
                

NET 6, System.Text.Json supports 'IAsyncEnumerable' 2

                    
                        JsonSerializerOptions options = new()
                        { WriteIndented = true };
            
                        using Stream stream = Console.OpenStandardOutput();
            
                        var data = new { Number = GetNumbersAsync() };
            
                        await JsonSerializer.SerializeAsync
                            (stream, data, options);
                    
                
CW
Copyright © 2021 Cezary Walenciuk
NET 6, System.Text.Json supports Streams

NET 6, System.Text.Json supports Streams

                    
                        public class ToRemember
                        {
                            public string Conference { get; set; }
                        }
                    
                

NET 6, System.Text.Json supports Streams

                    
                        JsonSerializerOptions options = new()
                        { WriteIndented = true };
                        
                        using Stream outputStream = Console.OpenStandardOutput();
                        
                        ToRemember to = new() { Conference = "5Developers" };
                        
                        JsonSerializer.Serialize<ToRemember>(outputStream
                        ,to,options);
                    
                

NET 6, System.Text.Json supports Streams

                    
                        string json = "{\"Conference\":\"4Developers\"}";

                        byte[] bytes = Encoding.UTF8.GetBytes(json);
                        
                        using MemoryStream ms = new MemoryStream();
                        
                        ToRemember toRemember =
                            JsonSerializer.Deserialize<ToRemember>(ms);
                        
                        Console.WriteLine(toRemember.Conference);
                    
                
What is the new style of programming in C# 10?
Minimal applications
Changes for creating minimal applications
  1. Why Minimal applications in .NET
  1. Why Minimal applications in .NET
File-Scoped Namespaces

File-Scoped Namespaces

                    
                        namespace ViewerApp.Models
                        {
                            public class Viewer
                            {
                                public string? FirstName { get; set; }
                                public string? LastName { get; set; }
                                public string? StreetAddress { get; set; }
                            }
                        }
                    
                

File-Scoped Namespaces 2

                    
                        namespace ViewerApp.Models;

                        public class Viewer2
                        {
                            public string? FirstName { get; set; }
                            public string? LastName { get; set; }
                            public string? StreetAddress { get; set; }
                        }
                    
                
CW
Copyright © 2021 Cezary Walenciuk
CW
Copyright © 2021 Cezary Walenciuk
CW
Copyright © 2021 Cezary Walenciuk
CW
Copyright © 2021 Cezary Walenciuk
CW
Copyright © 2021 Cezary Walenciuk
Implicit global usings

.NET 5 without implicit usings

                    
                        using System;
                        using System.Collections.Generic;
                        using System.Threading.Tasks;
                        
                        Console.WriteLine("Daj pozytwna ocene");
                        await Task.Delay(2000);
                        
                        List<string> list = new List<string>();
                        list.Add("Tej prelekcj");
                    
                

Turning on Implicit usings

                    
                        <Project Sdk="Microsoft.NET.Sdk">

                            <PropertyGroup>
                            <OutputType>Exe</OutputType>
                            <TargetFramework>net6.0</TargetFramework>
                            <ImplicitUsings>enable</ImplicitUsings>
                            <Nullable>enable</Nullable>
                            </PropertyGroup>
                        
                        </Project>
                    
                

.NET 5 without implicit usings

                    
                        //using System;
                        //using System.Collections.Generic;
                        //using System.Threading.Tasks;
                        
                        Console.WriteLine("Daj pozytwna ocene");
                        await Task.Delay(2000);
                        
                        List<string> list = new List<string>();
                        list.Add("Tej prelekcj");
                    
                
CW
Copyright © 2021 Cezary Walenciuk

ConsoleAppNET6CSharp10.GlobalUsings.g.cs

                    
                        // <auto-generated/>
                        global using global::System;
                        global using global::System.Collections.Generic;
                        global using global::System.IO;
                        global using global::System.Linq;
                        global using global::System.Net.Http;
                        global using global::System.Threading;
                        global using global::System.Threading.Tasks;
                    
                

For web application

                    
                        // <autogenerated />
                        global using global::System;
                        global using global::System.Collections.Generic;
                        global using global::System.IO;
                        global using global::System.Linq;
                        global using global::System.Net.Http;
                        global using global::System.Threading;
                        global using global::System.Threading.Tasks;
                        global using global::System.Net.Http.Json;
                        global using global::Microsoft.AspNetCore.Builder;
                        global using global::Microsoft.AspNetCore.Hosting;
                        global using global::Microsoft.AspNetCore.Http;
                        global using global::Microsoft.AspNetCore.Routing;
                        global using global::Microsoft.Extensions.Configuration;
                        global using global::Microsoft.Extensions.DependencyInjection;
                        global using global::Microsoft.Extensions.Hosting;
                        global using global::Microsoft.Extensions.Logging;
                    
                

Adding namespaces in project

                    


                        <Project Sdk="Microsoft.NET.Sdk">
                            <PropertyGroup>
                            <OutputType>Exe</OutputType>
                            <TargetFramework>net6.0</TargetFramework>
                            <ImplicitUsings>enable</ImplicitUsings>
                            <Nullable>enable</Nullable>
                            </PropertyGroup>
                            <ItemGroup>
                            <Using Include="System.Text.Json" />
                            <Using Include="System.Text.Json.Serialization" />
                            <Using Remove="System.IO" />
                            <Using Include="System.Console" Static="True" />
                            <Using Include="System.DateTime" Alias="DT" />
                            </ItemGroup>
                        </Project>
                      
                    
                
CW
Copyright © 2021 Cezary Walenciuk

Adding namespaces in code

                    
                        global using ViewerApp.Models;
                        global using static System.Console;
                        global using DT = System.DateTime;
                    
                
CW
Copyright © 2021 Cezary Walenciuk
Changes in Visual Studio Templates
Console Template
📃

Console Template for .NET 2-5

                    
                        using System;

                        namespace ConsoleApplication87
                        {
                            class Program
                            {
                                static void Main(string[] args)
                                {
                                    Console.WriteLine("Hello, World!");
                                }
                            }
                        }
                    
                

Console Template for .NET 6

                    
                        // See https://aka.ms/new-console-template for more information
                        Console.WriteLine("Hello, World!");
                    
                
ASP.NET Web Template
📃
CW
Copyright © 2021 Cezary Walenciuk
CW
Copyright © 2021 Cezary Walenciuk
CW
Copyright © 2021 Cezary Walenciuk
CW
Copyright © 2021 Cezary Walenciuk
CW
Copyright © 2021 Cezary Walenciuk
CW
Copyright © 2021 Cezary Walenciuk
CW
Copyright © 2021 Cezary Walenciuk

Program.cs in ASP.NET Empty template for .NET 6

                    
                        var builder = WebApplication.CreateBuilder(args);
                        var app = builder.Build();
                        
                        if (app.Environment.IsDevelopment())
                        {
                            app.UseDeveloperExceptionPage();
                        }
                        
                        app.MapGet("/", () => "Hello World!");
                        
                        app.Run();
                    
                

Program.cs in ASP.NET Web template for .NET 6

                    
                        var builder = WebApplication.CreateBuilder(args);

                        // Add services to the container.
                        builder.Services.AddControllersWithViews();
                        
                        var app = builder.Build();
                        
                        // Configure the HTTP request pipeline.
                        if (app.Environment.IsDevelopment())
                        {
                            app.UseDeveloperExceptionPage();
                        }
                        else
                        {
                            app.UseExceptionHandler("/Home/Error");
                            // The default HSTS value is 30 days.
                            app.UseHsts();
                        }
                        
                        app.UseHttpsRedirection();
                        app.UseStaticFiles();
                        
                        app.UseRouting();
                        
                        app.UseAuthorization();
                        
                        app.MapControllerRoute(
                            name: "default",
                            pattern: "{controller=Home}/{action=Index}/{id?}");
                        
                        app.Run();
                    
                
How easy is to create ASP.NET Core App from nothing
CW
Copyright © 2021 Cezary Walenciuk
CW
Copyright © 2021 Cezary Walenciuk
CW
Copyright © 2021 Cezary Walenciuk
CW
Copyright © 2021 Cezary Walenciuk
CW
Copyright © 2021 Cezary Walenciuk
CW
Copyright © 2021 Cezary Walenciuk

How easy is to create ASP.NET Core App from nothing

                    
                        var builder = WebApplication.CreateBuilder(args);

                        builder.Services.AddSingleton<HelloService>
                            (new HelloService());
                        
                        var app = builder.Build();
                        
                        app.MapGet("/", () => "Daj dobrą ocenę");
                        app.MapGet("/hello", (HttpContext context, HelloService service)
                             => service.SayHello(context.Request.Query["name"]
                             .ToString()));
                        
                        await app.RunAsync();
                        
                        public class HelloService
                        {
                            public string SayHello(string name)
                            {
                                return $"Hello {name}";
                            }
                        }
                        
                    
                
One file mess ?
Ok, then divide endpoints to static classes
🤷‍♂️

Routes

                    
                        public static class Routes
                        {
                            public static IEndpointRouteBuilder UseHelloEndpoint
                                (this IEndpointRouteBuilder endpoints)
                            {
                                endpoints.MapPost("api/hello", async context =>
                                {
                        
                                });
                        
                                return endpoints;
                            }
                        }
                    
                
Why would I divide the endpoints like that into separate definition classes?

It makes the minimal API look almost like the old controller-based approach.
Minimal APIs maybe would perform much better than controller-based APIs ?
😨
Yes, kinda
😅
Show me better solution for Minimal APIs ?

EndPointDefinitionExtension and IEndpointDefinition

                    
                        public class EndpointDefinition : IEndpointDefinition
                        {
                            public void DefineEndpoints(WebApplication app)
                            {
                                app.MapPost("api/hello", async context =>
                                {
                        
                                });
                            }
                        
                            public void DefineServices(IServiceCollection services)
                            {
                                
                            }
                        }
                    
                

EndPointDefinitionExtension and IEndpointDefinition 2

                    
                        public interface IEndpointDefinition
                        {
                            void DefineServices(IServiceCollection services);
                        
                            void DefineEndpoints(WebApplication app);
                        }
                    
                

EndPointDefinitionExtension and IEndpointDefinition 3

                    
















                        public static class EndPointDefinitionExtension
                        {
                            public static void AddEndpointDefinitions(
                                this IServiceCollection services,params Type[] scanMarkers)
                            {
                                var endpoints = new List<IEndpointDefinition>();
                        
                                foreach (var scanMarker in scanMarkers)
                                {
                                    endpoints.AddRange(
                                        scanMarker.Assembly.ExportedTypes
                                        .Where(x => typeof(IEndpointDefinition)
                                        .IsAssignableFrom(x) && (!x.IsInterface && !x.IsAbstract))
                                        .Select(Activator.CreateInstance)
                                        .Cast<IEndpointDefinition>()
                                    );
                                }
                        
                                foreach (var endpoint in endpoints)
                                {
                                    endpoint.DefineServices(services);
                                }
                        
                                services.AddSingleton
                                    (endpoints as IReadOnlyCollection<IEndpointDefinition>);
                            }
                        
                            public static void UseEndpointDefinitions(this WebApplication app)
                            {
                                var defs = app.Services.
                                GetRequiredService<IReadOnlyCollection<IEndpointDefinition>>();
                        
                                foreach (var def in defs)
                                {
                                    def.DefineEndpoints(app);
                                }
                            }
                        }
                    
                

Program.cs

                    
                        var builder = WebApplication.CreateBuilder(args);

                        builder.Services.AddEndpointDefinitions
                        (typeof(EndpointDefinition));

                        var app = builder.Build();
                        
                        app.UseEndpointDefinitions();
                        app.Run();
                    
                
Another example
😉
How easy is to create SignalR App from nothing
CW
Copyright © 2021 Cezary Walenciuk

Program.cs Server SignalR App

                    
                        var builder = WebApplication.CreateBuilder(args);

                        builder.Services.AddSignalR();
                        builder.Services.AddCors(options =>
                        {
                            options.AddPolicy("CorsPolicy", builder => builder
                                .WithOrigins("http://localhost:56675")
                                .AllowAnyMethod()
                                .AllowAnyHeader()
                                .AllowCredentials());
                        });
                        
                        var app = builder.Build();
                        
                        app.UseCors("CorsPolicy");
                        app.MapHub<MyHub>("/chat");
                        app.MapHub<ChartHub>("/chart");
                        app.Run();
                    
                

MyHub

                    
                        public class MyHub : Hub
                        {
                            public async IAsyncEnumerable<string> Streaming
                            (CancellationToken stoppingToken)
                            {
                                while (!stoppingToken.IsCancellationRequested)
                                {
                                    if (_random.Next(0, 10) < 5)
                                        yield return DateTime.UtcNow.ToString("hh:mm:ss");
                        
                                    try
                                    {
                                        await Task.Delay(1000,stoppingToken);
                                    }
                                    catch (OperationCanceledException)
                                    {
                                        yield break;
                                    }
                                }
                            }
                        
                            private Random _random = new Random();
                        }
                    
                
CW
Copyright © 2021 Cezary Walenciuk
CW
Copyright © 2021 Cezary Walenciuk

Program.cs Client SignalR App

                    
                        using Microsoft.AspNetCore.SignalR.Client;

                        var uri = "http://localhost:5000/chat";
                        
                        await using var connection = new HubConnectionBuilder()
                            .WithUrl(uri)
                            .Build();
                        
                        
                        await connection.StartAsync();
                        
                        
                        await foreach (var item in
                            connection.StreamAsync<string>("Streaming"))
                        {
                            Console.WriteLine(item);
                        }
                    
                
CW
Copyright © 2021 Cezary Walenciuk
  1. Minimal applications in ASP.NET Core
Other changes in C# 10

In C# 10 you can also use 'with' expression with struct types

                    
                        Drink drink = new () { Fat = 20, TotalVolume= 200};

                        Drink green = drink with { Fat = 40};
                        
                        public struct Drink
                        {
                            public int Fat { get; set; }
                            public int TotalVolume { get; set; }
                        }
                    
                

If the struct has field initializers, the compiler will synthesize a public parameterless constructor

                    
                        public struct Drink
                        {
                            public int Fat { get; set; } = 1;
                            public int TotalVolume { get; set; } = 2;
                        }
                    
                

Record struct

                    
                        record struct DrinkRecord(int fat, int totalVolume);
                    
                

Explicit return types in lambdas

                    
                        var a1 = string () => string.Empty;

                        var a2 = int () => int.MaxValue;

                        var a3 = static void () => { };

                        var a4 = string? () => null;
                        
                        public static void Example<T>()
                        {
                            var a5 = T () => default;
                        }
                    
                

MyAttribute in lambdas

                    
                        Func<int> f1 = [MyAttribute] () => { return 0; };
                        Func<int> f2 = [return: MyAttribute] () => { return 0; };
                        Func<int,int> f3 = ([MyAttribute] x)=> { return x; };
                        
                        class MyAttribute : Attribute
                        {
                        
                        }
                    
                

C# 10 can do both assignment and declaration in the same deconstruction

                    
                        int a;int b;
                        (a, int r, int g,b) = (255, 100, 0, 150);
                    
                
CW
Copyright © 2021 Cezary Walenciuk

You can add sealed keyword in override in C# 10

                    
                        public record Game
                        {
                            public sealed override string ToString()
                            {
                                return base.ToString();
                            }
                        }
                    
                

You can reference nested properties or fields within a proper pattern

                    
                        var speech = new { Speaker = new { Name = "C" } };

                        //C# 9
                        if (speech is { Speaker: { Name :"C"} }) { }
                        
                        //C# 10
                        if (speech is { Speaker.Name: "C"}) { }
                    
                

Initializing 'const' strings using string interpolation, but the placeholder must also be a 'const' string

                    
                        const string NAME = "MyApplication";
                        const string FULLNAME = $"{NAME} 1.20";
                        
                        const double VERSIONP = 1.20;
                        //const string FULLNAME2 = $"{NAME} {VERSIONP}";
                    
                
And now what I promise
Static abstract methods in Interface

Static abstract methods in Interface. Maybe in .NET 7

                    
                        public interface ICreatable<TSelf, TArg1, TArg2, TArg3>
                        where TSelf : ICreatable<TSelf, TArg1, TArg2, TArg3>
                        {
                            static abstract TSelf Create(TArg1 arg1,
                                TArg2 arg2, TArg3 arg3);
                        }
                    
                

Static abstract methods in Interface. Maybe in .NET 7

                    
                        public class Game : ICreatable<Game, string, string, int>
                        {
                            public Game(string name, string desc, int year)
                            {
                                Name = name; Description = desc; Year = year;
                            }
                        
                            public string Name { get; set; }
                            public string Description { get; set; }
                            public int Year { get; set; }
                        
                            public static Game Create
                                (string name, string desc, int year)
                            {
                                return new Game(name, desc, year);
                            }
                        }

                        Game.Create("a", "a", 1);
                    
                

Static abstract methods in Interface. Maybe in .NET 7

                    
                        static T Add<T>(T left, T right) where T : INumber<T>
                        {
                            return left + right;
                        }
                        
                        static T ParseInvariant<T>(string s) where T : IParseable<T>
                        {
                            return T.Parse(s,
                                CultureInfo.InvariantCulture);
                        }
                        
                        Console.Write("First number: ");
                        var left = ParseInvariant<float>(Console.ReadLine());
                        
                        Console.Write("Second number: ");
                        var right = ParseInvariant<float>(Console.ReadLine());
                        
                        Console.WriteLine($"Result: {Add(left, right)}");
                    
                
Before I say goodbye...check also Visual Studio 2022
CW
Copyright © 2021 Cezary Walenciuk