04 Feb

Exploring C# 12 Features

As technology evolves, programming languages continue to advance, offering developers new tools and features to enhance their productivity and simplify complex tasks. In the world of .NET development, C# remains a prominent language, constantly evolving to meet the needs of modern software development. C# 12, the latest iteration of this language, introduces several compelling features that streamline code, improve readability, and empower developers. In this blog post, we’ll delve into five thrilling enhancements in C# 12 that particularly captivate my interest.

Prerequires needs to be setup for reviewing C# 12 features.

  1. VS 2022  version 17.7  Or
  2. .NET 8.0 SDK

Source code can be downloaded from GitHub.

 1. Primary Constructors

This feature simplifies the initialization of properties in a class by allowing you to declare them directly within the constructor parameters, reducing boilerplate code. Here’s a quick example:

namespace PrimaryConstructor
    internal class Person(string name, int age)
        // Constructor body is empty as properties are initialized directly in the parameter list
        public string Name { get; } = name;
        public int Age { get; } = age;

This concise syntax eliminates the need for separate property declarations and assignments within the constructor body, making the code more readable and maintainable.

Please refer the Microsoft Learning for more information on Primary Constructor.

2. Collection Expression

C# 12 introduces collection expressions, enabling the creation and initialization of collections directly within object initializers and collection initializers. It allows for a more compact and readable syntax when working with collections. For instance:

Console.WriteLine("Collection Expression");

//array initializtion using collection expression
int[] numbers = { 1, 2, 3, 4, 5 };

int[] number1 = { 1, 2, 3 };
int[] number2 = { 4, 5, 6 };
int[] number3 = { 7, 8, 9 };

int[] merge = [..number1, ..number2, ..number3];

//var cannot be used with collection expressions
//var digits = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 

Console.WriteLine($"Merge: {string.Join(",", merge)}");

This enhancement simplifies the initialization of arrays, lists, dictionaries, and other collections, reducing verbosity and improving code clarity.

Please refer the Microsoft Learning for more details on Collection Expression.

3. Ref Readonly Parameters

Ref readonly parameters provide a way to pass parameters by reference while ensuring they cannot be modified within the method. This feature enhances performance by avoiding unnecessary copying of large structs while maintaining immutability. Here’s an example:

namespace RefReadOnlyParameter
    public class Example
        public void MethodWtithoutRefReadOnlyParameter(ref int age)
            Console.WriteLine($"Age: {age}");
            age = 50;

        public void MethodWithRefReadOnlyParameter(ref readonly int age)
            //age = 50; //Error CS8331 Cannot assign to variable 'in int' because it is a readonly variable
            Console.WriteLine($"Age: {age}");
using RefReadOnlyParameter;

Console.WriteLine("Ref Readonly Parameter!");

int age = 42;
var example = new Example();
Console.WriteLine("Ref Parameter!");
example.MethodWtithoutRefReadOnlyParameter(ref age);
Console.WriteLine($"Age: {age}");

Console.WriteLine("Ref Readonly Parameter!");

example.MethodWithRefReadOnlyParameter(ref age);
Console.WriteLine($"Age: {age}");

Ref readonly parameters offer a balance between performance and immutability, improving code safety and efficiency.

Please refer Microsoft Learning for more information on Ref Readonly parameters.

4. Default Lambda Parameters

C# 12 introduces default values for lambda parameters, allowing developers to define default arguments within lambda expressions. This feature enhances flexibility when working with lambdas by providing default values for parameters. For example:

Console.WriteLine("Default Lambda Parameters!");

var lambdaDefaultParameter = (int age = 38) => Console.WriteLine($"Age: {age}");




This enables functions to be invoked with fewer arguments when default values are provided, reducing code redundancy.

Please refer Microsoft Learning for more information.

5. Alias Any Type

The latest update in C# 12 has eased the using alias directive, enabling the aliasing of various types beyond just named types. This expansion allows for the aliasing of tuples, pointers, array types, generic types, and more. Consequently, instead of employing the complete structural representation of a tuple, you can now assign it a concise, descriptive name and utilize it across your codebase.

For example,

using circleType = (int X, int Y, int Radius);

var circle = new circleType(10, 10, 20);
//we can declare in the below way also
//circleType circle = (10, 10, 20);

Console.WriteLine($"X: {circle.X}, Y: {circle.Y}, Radius: {circle.Radius}");

Please refer the Microsoft Learning for more information

There are a few more features such as Inline Arrays, Experimental Attribute and Interceptors ( which is still in preview stage).

About the Author

Comments are closed.