- C# - Home
- C# - Overview
- C# - Environment
- C# - Program Structure
- C# - Basic Syntax
- C# - Data Types
- C# - Type Conversion
- C# - Variables
- C# - Constants
- C# - Operators
- C# - Arithmetic Operators
- C# - Assignment Operators
- C# - Relational Operators
- C# - Logical Operators
- C# - Bitwise Operators
- C# - Miscellaneous Operators
- C# - Operators Precedence
- C# Conditional Statements
- C# - Decision Making
- C# - If
- C# - If Else
- C# - Nested If
- C# - Switch
- C# - Nested Switch
- C# - Switch Expressions
- C# Control Statements
- C# - Loops
- C# - For Loop
- C# - While Loop
- C# - Do While Loop
- C# - Nested Loops
- C# - Break
- C# - Continue
- C# - Foreach Loop
- C# - Goto Statement
- C# OOP & Data Handling
- C# - Encapsulation
- C# - Methods
- C# - Nullables
- C# - Arrays
- C# - Strings
- C# - Structure
- C# - Enums
- C# - Classes
- C# - Inheritance
- C# - Polymorphism
- C# - Operator Overloading
- C# - Interfaces
- C# - Namespaces
- C# - Preprocessor Directives
- C# - Regular Expressions
- C# - Exception Handling
- C# - File I/O
- C# Advanced Tutorial
- C# - Attributes
- C# - Reflection
- C# - Properties
- C# - Indexers
- C# - Delegates
- C# - Events
- C# - Collections
- C# - Generics
- C# - LINQ
- C# - IEnumerable vs IEnumerator
- C# - Anonymous Methods
- C# - Unsafe Codes
- C# - Tasks and Parallel Programming
- C# - Multithreading
- C# - Extension Methods
- C# - Async and Await
- C# Modern Features
- C# - Tuples
- C# - Pattern Matching Enhancements
- C# - Nullable Reference Types
- C# - What's New in C# 11 / 12 / 13
- C# Practical & Advanced Usage
- C# - JSON & XML Handling
What's New in C# 11 / 12 / 13
C# is getting more maintainable and readable with each new version; it introduces additional features that make the code easier to read, run faster and be concise with meaningful impact.
Let's explore what's new in C# 11, C# 12, and C# 13, and how these updates simplify real-world development.
C# 11
C# 11 released with .NET 7 focused on the performance, pattern matching, and developer convenience. Let's see what they have introduced −
- Raw String Literals
- List Patterns
- Required Members
- Generic Math Support
- UTF-8 String Literals
Raw String Literals
The raw string literal can contain any arbitrary text without requiring special escape sequences such as quotes or newlines. It is especially useful for representing JSON, SQL, or HTML blocks.
A raw string literal starts and ends with a minimum of three double-quote (") characters.
string json = """
{
"name": "Aman",
"language": "C#"
}
""";
Console.WriteLine(json);
List Patterns
In C#, list patterns is useful to match array or list structure directly.
int[] numbers = { 1, 2, 3 };
if (numbers is [1, 2, 3])
Console.WriteLine("Matched the exact pattern!");
Required Members
In C#, the required members feature introduces the required modifier. It is applied to a property or field that must be initialized when an object of the containing type is created. This ensures that specific members are always assigned a value during object construction.
public class User {
public required string Name { get; init; }
public int Age { get; init; }
}
var user = new User { Name = "Aman", Age = 25 }; // valid
Generic Math Support
In C#, the generic math support internally uses the generic interface and default methods of the interface. The default method of the interface was introduced with C# 8.
To use generic math, we first need to import the following namespace: using System.Numerics; Let's understand by a code snippet −
using System.Numerics;
T Add<T>(T first, T second) where T : INumber<T> {
// INumber interface is part of the System.Numerics namespace.
T result = 0;
result = first + second;
return result;
}
UTF-8 String Literals
In C# 11.0 and C++20, it allow for the direct representation of string constants in UTF-8 encoding. This provides performance and interoperability benefits, particularly when working with web protocols or libraries that commonly use UTF-8.
ReadOnlySpan<byte> data = "Hello"u8;
C# 12
C# 12 released with .NET 8 focused on the data programming and simplicity. Let's see what they have introduced −
- Primary Constructors for Classes and Structs
- Collection Expressions
- Inline Arrays
- Alias Any Type
- Default Lambda Parameters
Primary Constructors for Classes and Structs
In C# 12, the Primary Constructors feature allows us to define constructor parameters directly in the class or struct declaration. It means we no longer need to write a separate constructor body to assign parameter values to fields.
It provides a more concise way to initialize data members, especially in small data-centric types.
public class Person(string name, int age) {
public void Show() => Console.WriteLine($"{name}, {age}");
}
var p = new Person("Aman", 25);
p.Show();
Explanation: Here, name and age are defined directly in the class declaration. They are available throughout the class just like constructor parameters, making the code more compact and understandable.
Collection Expressions
In C#, the Collection Expressions introduces a simpler syntax to create arrays, lists, and spans using square brackets ([]),
omitting the need for explicit new or new List<T> constructors. It provides a more consistent and readable way to initialize collections.
int[] arr = [1, 2, 3]; List<string> names = ["Aman", "John", "Sara"];
Explanation: The compiler automatically infers the collection type based on the variable declaration. This makes initialization concise and clear, particularly for scenarios where many collections are declared.
Inline Arrays
In C#, the Inline Arrays allows us to define fixed-size arrays directly inside structs for performance-critical scenarios. It helps reduce memory allocations and improves cache locality, that is beneficial in low-level or high-performance applications.
[System.Runtime.CompilerServices.InlineArray(3)]
public struct Numbers {
private int _element0;
}
var n = new Numbers();
Explanation − Here, the InlineArray attribute defines a structure that behaves like an array of three integers. This approach avoids heap allocations and is particularly useful in game engines or systems programming where performance is crucial.
Alias Any Type
In C#, after the introduction of C# 12, we can now create Type Aliases for any type, including tuples, arrays, and generic types. This improves code readability and reusability, especially in large projects where complex type names are frequently used.
using MyNumber = (int X, int Y); MyNumber point = (10, 20);
Explanation − The using alias directive lets us assign a short, descriptive name to a complex type. In this example, MyNumber acts as an alias for a tuple of two integers, making the code cleaner and easier to maintain.
Default Lambda Parameters
In C# 12, introduces Default Lambda Parameters, that allow lambda expressions to have parameters with default values. This avoid the need to overload methods or define multiple lambdas for different argument combinations.
var greet = (string name = "Guest") => $"Hello, {name}!";
Console.WriteLine(greet()); // Output: Hello, Guest!
Console.WriteLine(greet("Aman")); // Output: Hello, Aman!
Explanation: Here, the lambda parameter name has a default value of "Guest".
If no argument is passed when calling the lambda, it automatically uses the default value. This feature makes lambdas more flexible and reduces redundant code in scenarios like logging, greetings, or optional configurations.
C# 13
C# 13 is still in preview and continues to refine syntax and flexibility. Let's see what has been introduced −
- Params Collections
- Lock Object Expression
- Partial Properties and Indexers
- Using Alias for Any Type
Params Collections
In C# 13, the params keyword has been enhanced to support collections, not just arrays.It means we can now pass lists or other collection types directly to a method that uses params. It makes method calls more flexible and consistent with modern C# collection syntax.
void Print(params List<int> numbers) {
foreach (var n in numbers)
Console.WriteLine(n);
}
Print([1, 2, 3, 4]);
Explanation
In earlier C# versions, params only worked with arrays (like int[]). With C# 13, we can use params with lists and other compatible collection types, making it easier to handle variable-length arguments using modern syntax.
Lock Object Expression
C# 13 improves thread safety with a more flexible lock expression.
We can now safely lock on ref variables and other complex expressions.
This feature helps developers write safer and more efficient multithreaded code.
object sync = new();
lock (sync) {
Console.WriteLine("Thread-safe section");
}
Explanation − The lock statement prevents multiple threads from accessing the same code block at the same time. With C# 13, we can use more types of expressions in the lock, giving us better control over synchronization in multi-threaded environments.
Partial Properties and Indexers
C# 13 allows developers to declare partial properties and partial indexers. We can split the implementation of a property or indexer across multiple partial class files. It is useful when working on large projects where multiple developers might share class definitions.
public partial class Product {
public partial int Price { get; set; }
}
Explanation
This feature extends the existing concept of partial classes to include properties and indexers. It improves maintainability by allowing developers to organize code logically across files, especially when auto-generated and manually written code coexist.
Using Alias for Any Type
In C# 13, the using alias directive has been expanded to support more complex type scenarios. We can now create aliases for almost any type, including generic types, tuples, and types defined in nested namespaces.
using MyTuple = (int Id, string Name);
MyTuple user = (1, "Aman");
Console.WriteLine($"{user.Id}, {user.Name}");
Explanation
The using alias concept helps simplify long or complex type names by creating shorter, descriptive names. In C# 13, it now works with more advanced type definitions, improving code readability and making large projects easier to manage.
Conclusion
When a new version of C# is released, each update enhances productivity and makes the language more modern and expressive. If we are upgrading your project, check .NET SDK version and enable the latest C# version in project file.
<PropertyGroup> <LangVersion>preview</LangVersion> </PropertyGroup>