With every new release, C# continues to evolve, making it easier to write efficient, clean, and maintainable code. C# 12 is packed with exciting new features that simplify complex tasks, reduce boilerplate code, and enhance readability. Whether you're a seasoned C# developer or just diving into the language, these new features will help you write better code with less effort.
In this post, we'll explore some of the most impactful features introduced in C# 12, along with practical examples to show how they can streamline your workflow and boost productivity.
1. Primary Constructors for Non-Record Classes
Primary constructors, previously exclusive to records, are now available for non-record classes in C# 12. This feature allows you to define constructor parameters directly in the class declaration, reducing boilerplate code and improving readability.
Example:
public class Employee(string name, int id)
{
public string Name { get; } = name;
public int Id { get; } = id;
}
With primary constructors, there's no need to define a separate constructor or set properties manually, making your classes more concise and easier to read.
2. Collection Expressions
Collection expressions are a new way to initialize collections using concise syntax. They allow you to define collections with a simpler, more intuitive syntax, which is especially useful when working with complex data structures.
Example:
var numbers = [1, 2, 3, 4, 5];
var names = ["Alice", "Bob", "Charlie"];
This feature is not only cleaner but also makes your code more readable, reducing the verbosity associated with traditional collection initializers.
3. Default Lambda Parameter Values
Setting default values for lambda parameters is a long-awaited feature that has finally arrived in C# 12. This allows you to specify default values for parameters in lambda expressions, which is particularly useful for event handling or custom delegates.
Example:
Func<int, int, int> add = (a, b = 5) => a + b;
Console.WriteLine(add(10)); // Output: 15
Default lambda parameters enhance flexibility, letting you create more adaptable lambdas without needing to overload or redefine the expression.
4. Interpolated String Handlers with Custom Logic
C# 12 introduces the ability to create custom interpolated string handlers, enabling you to control the behavior of string interpolation at a granular level. This feature is perfect for logging, formatting, and managing memory in performance-sensitive applications.
Example:
public class CustomLogger
{
public void Log(string message) => Console.WriteLine(message);
public void LogInterpolated(string message)
{
Log($"[INFO] {message}");
}
}
With custom interpolated string handlers, you can create efficient and tailored logging or formatting solutions that adapt to specific scenarios.
5. Primary Constructor with Field Keywords
C# 12 brings the ability to declare primary constructor parameters as fields directly. This feature eliminates the need to declare additional properties or fields, which helps reduce boilerplate code.
Example:
public class Point(public int x, public int y);
This feature makes code more compact, as there’s no need to manually create properties or fields for constructor parameters.
6. Inline Collections with Ranges and Slices
Inline collections can now work with ranges and slices in C# 12, making it easier to access specific parts of collections without additional indexing logic. This feature is ideal for cases where you need quick access to a subset of data in arrays or lists.
Example:
var array = [1, 2, 3, 4, 5];
var subArray = array[1..3]; // Output: [2, 3]
This enhancement increases readability and flexibility when working with collections, as you can access ranges directly without extra steps.
7. Enhanced Switch Expressions with Named Variables
Switch expressions have been enhanced with the capability to use named variables, making them more powerful for pattern matching and logical control. This feature allows for more descriptive and maintainable switch statements.
Example:
var result = shape switch
{
Circle c => $"Circle with radius {c.Radius}",
Square s => $"Square with side length {s.SideLength}",
_ => "Unknown shape"
};
Named variables in switch expressions allow for easier access to properties in complex conditional logic, enhancing the expressiveness of your code.
8. File-Scoped Types
File-scoped types, now available in C# 12, allow you to define types scoped to a single file, providing better encapsulation. This feature is useful when you want to prevent certain types from being accessible across multiple files, promoting better organization in large projects.
Example:
file class Helper
{
public static void Assist() => Console.WriteLine("Assisting...");
}
By scoping types to a single file, you can control accessibility and reduce potential conflicts in larger codebases.
9. Improved nameof
Expressions
In C# 12, the nameof
operator can now be used with parameters, locals, and types. This enhancement makes it easier to work with dynamic code where you need reliable names for variables and types.
Example:
void DisplayName(string paramName)
{
Console.WriteLine(nameof(paramName)); // Output: "paramName"
}
This small improvement can make debugging and logging easier by allowing you to capture names directly without relying on string literals.
10. With-Expressions for Non-Records
With-expressions, previously exclusive to records, are now available for classes in C# 12. This feature allows you to clone objects with modified properties without altering the original instance.
Example:
var original = new Person { Name = "Alice", Age = 30 };
var modified = original with { Age = 31 };
With-expressions simplify object manipulation, especially in immutable data patterns, and they enhance code readability by reducing unnecessary constructors.
Why You Should Start Using C# 12 Today
These new features in C# 12 are designed to make your code cleaner, more efficient, and easier to maintain. Whether you’re a seasoned developer or just getting started, adopting these features can help you write better C# code with minimal effort.
Conclusion
C# 12 brings powerful new tools that simplify coding and make it more expressive. From primary constructors for non-record classes to enhanced switch expressions and with-expressions for non-records, these updates reduce boilerplate and boost productivity.
By mastering these features, you'll be ready to write cleaner, more maintainable code with the latest that C# has to offer. If you're already using .NET 8 or planning to, upgrading to C# 12 is a no-brainer to take full advantage of the latest language advancements.