C# 14 introduces one of the most requested language features in years: Extension Members.
While C# has long supported extension methods, the new extension member system dramatically expands what developers can add to types they don’t control, enabling us to do pretty much whatever we want with non-user types 🔥
In this article, we’ll try to explain what are those new extension members and how to use it properly, so let’s go !
What are Extension Members?
Traditionally, C# extension methods let you add methods to a type without modifying its source code. But you were limited to methods: no properties, no operators, and no static members.
C# 14 finally changes that !
Extension Members provide a new syntax that lets you define:
- Instance extension properties
- Instance extension methods
- Static extension properties and methods
- Extension operators
All of this can now be grouped together in an extension block tied to a target type.
How it works & why this matters
This feature unlocks a much richer way to extend types without inheritance or source access:
More expressive APIs
For instance, instead of writing this:
public static class EnumerableExtensions
{
public static bool IsEmpty<T>(this IEnumerable<T> source) => !source.Any();
}
You can now write:
public static class EnumerableExtensions
{
extension<T>(IEnumerable<T> source)
{
public bool IsEmpty => !source.Any();
}
}
Now extension properties look and feel like native members on the type itself 🔥
A now grouped & DRY syntax
Instead of repeating the receiver type for every member (as you would normally do with the keyword this in classic extension methods), the new extension block declares the receiver once and nests all related members inside it.
This clearly reduces boilerplate and improves readability.
Also note that:
- Extension members still don’t modify the original type: they simply appear as if they’re part of it.
- Existing extension methods using the
thissyntax still work. The new syntax is optional and completely interoperable.
Practical examples
Here are some practical examples showing you how to write extension members using:
- Static properties tied to the extended type
- Static helper methods
- Custom operators
Extension property
public static class EnumerableExtensions
{
extension<T>(IEnumerable<T> source)
{
public static bool IsLong => source.Count() > 10;
}
}
Usage:
if (messages.IsLong) { … }
This reads like a built-in property, but it’s defined externally.
Static helper methods
public static class EnumerableExtensions
{
extension<T>(IEnumerable<T> source)
{
public static IEnumerable<T> Combine(
params IEnumerable<T>[] sources)
=> sources.SelectMany(s => s)
}
}
Usage:
var combined = IEnumerable<int>.Combine(
new[] { 1, 2 },
new[] { 3, 4 }
);
Extension operator
public static class EnumerableExtensions
{
extension<T>(IEnumerable<T> source)
{
public static IEnumerable<T> operator +(
IEnumerable<T> left,
IEnumerable<T> right) => left.Concat(right);
}
}
Usage:
IEnumerable<int> results = list1 + list2;
Now list1 + list2 will work even though IEnumerable itself doesn’t declare such an operator.
When to use Extension Members
Some good use cases:
- Adding computed properties like
IsEmpty,IsValid,IsCritical, etc. - Adding operators to types you can’t modify.
- Grouping related extensions in a readable way.
Not supported:
- You still cannot add actual fields to types as extension members don’t change the underlying memory layout.
What about an easy way for migrating existing code to this new syntax ?
You could want to migrate an existing project to this new members syntax when migrating to .NET 10, without necessarilly rewrite each of your existing methods.
And actually, Rider offers a simple way to do this easily (don’t ask me about VS, I don’t use it).
Simply go to one of your classic extensions methods, Alt+Enter on it and you’ll have a new fresh option “Convert this method to extension block” that will do the job for you ! 🔥
Unfortunately there is no way to apply this globally on a project or solution in one-shot, so you’ll have to do this on each method, but hey better than nothing !
Conclusion
Extension members in C# 14 are a pretty nice evolution of the extension mechanism:
- They expand capabilities beyond methods to include properties, static members, and operators.
- They provide a cleaner, centralized syntax via
extensionblocks. - They preserve compatibility with existing extension methods.
For any developer who loves to write expressive C# code, this is a very welcome addition to the language, one that makes code easier to write and customize without breaking the existing base.
Happy hacking & Merry Christmas 👨💻❤️🎅