If you remember the summary I made about C# 13 back in November, I mentioned a feature that wasn’t ready yet but was planned, extensions everywhere; and here we have an update on that news. With the arrival of C# 14 we’ll have what we now call extension members.
Table of Contents
For now, and until November 2025 with C# 14 (NET 10), the new feature is in preview and should not be used in production.
1 - Extension Methods
In C#, for many years we’ve had extension methods that allow us to extend the behavior of a class.
For example, and to use the same example provided in the official Microsoft announcement.
If we have an integer collection and we want to get those greater than X, we can do something like this:
List<int> values = new List<int> { 0,5,6,9,20,55,99 };
IEnumerable<int> result = values.WhereGreaterThan(18);
public static class Extensions
{
public static IEnumerable<int> WhereGreaterThan(this IEnumerable<int> source, int threshold)
=> source.Where(x => x > threshold);
}
Here we have a method that extends the IEnumerable
functionality using the this
keyword.
In my personal opinion this language feature is something I love and use all the time.
2 - Extension methods everywhere | Extension members
With C# 14, things are going to change a bit. Right now you need to do what we did earlier: create a static class and a static method, and the compiler knows how to resolve the method call and under the hood transforms this:
IEnumerable<int> result = values.WhereGreaterThan(18);
Into a call to the static class itself:
IEnumerable<int> result = Extensions::WhereGreaterThan(values, 18);
(the compiler does this for you)
In C# 14 or .NET 10, we’ll have a brand new keyword: extension
. With this keyword, we can change the previous code to the following:
public static class Extensions
{
extension(IEnumerable<int> source)
{
public IEnumerable<int> WhereGreaterThan(int threshold)
=> source.Where(x => x > threshold);
}
}
And the code works exactly as before.
At this point, you may wonder what’s the reason to introduce a new keyword. The answer is, we’re not just limited to methods now; we can also extend with properties. In this case, and to keep following the documentation’s example, let’s add an IsEmpty
property:
public static class Extensions
{
extension(IEnumerable<int> source)
{
public IEnumerable<int> WhereGreaterThan(int threshold)
=> source.Where(x => x > threshold);
public bool IsEmpty
=> !source.Any(); 👈
}
}
Which you can use in code like this:
List<int> values = new List<int> { 0,5,6,9,20,55,99 };
IEnumerable<int> result = values.WhereGreaterThan(18);
if (result.IsEmpty) 👈
{
Console.WriteLine("There is no elements on the list");
}
2.1 - Using generics in extension members
Just like extension methods, here we can also use generics, which means we can do something like this:
extension<T>(IEnumerable<T> source)
where T : INumber<T>
{
public IEnumerable<T> WhereGreaterThan(T threshold)
=> source.Where(x => x > threshold);
public bool IsEmpty
=> !source.Any();
}
And in this specific case, these extensions work with any numeric C# type: int, long, float, etc.
3 - Should We Migrate Extension Methods in C# 14?
One of the questions many of you might have is whether we need to migrate all our extension methods to the new form. The answer is no.
Both ways can coexist, and there is no need to switch.
What I would personally do is maintain consistency. If you’re on a project that heavily uses extension methods, just keep using them that way. However, if you’re starting a project from scratch and want to add new ones, you could discuss whether to use the new or old approach. What I do not recommend is mixing both, basically to keep the code as clean as possible.
If there is any problem you can add a comment bellow or contact me in the website's contact form