HomeNikola Knezevic

In this article

Banner

Extension Members in .NET

09 Apr 2026
4 min

Sponsor Newsletter

One of the exciting additions coming with .NET 10 and C# 14 is the introduction of extension members.

This feature expands on our beloved concept of extension methods, allowing us to finally add not only methods, but also instance members and properties to existing types without modifying source code.

Traditional Extension Methods

For years, extension methods have been the standard way to add functionality to existing types without modifying them directly.

Here's an example:

csharp
public static class EnumerableExtensions
{
    public static IEnumerable<int> WhereGreaterThan(this IEnumerable<int> source, int threshold)
    {
        return source.Where(x => x > threshold);
    }
}

And now you can use them like any other method:

csharp
var numbers = new List<int> { 1, 3, 5, 7, 9 };
var greater = numbers.WhereGreaterThan(5);

Console.WriteLine(greater.Count()); // Output: 2

This approach has served developers well.

However, it comes with its own limitations:

  • You can only add static methods
  • You cannot add properties or instance members

New Extension Members

C# 14 introduces yet another keyword: extension.

This enables defining extension blocks that contain multiple methods or properties for the same receiver type:

csharp
public static class EnumerableExtensions
{
    extension(IEnumerable<int> source)
    {
        public IEnumerable<int> WhereGreaterThan(int threshold)
            => source.Where(x => x > threshold);
    }
}

Now, you can call this method like before:

csharp
var numbers = new List<int> { 1, 3, 5, 7, 9 };
var greater = numbers.WhereGreaterThan(5);

Console.WriteLine(greater.Count()); // Output: 2

In my opinion, this syntax is cleaner and feels like a natural extension of the type.

Under the hood, the compiler still lowers extension members to regular static methods, ensuring full backward compatibility.

You can also make your extension blocks generic and even add constraints:

csharp
public static class EnumerableExtensions
{
    extension<T>(IEnumerable<T> source) where T : INumber<T>
    {
        public IEnumerable<T> WhereGreaterThan(T threshold)
            => source.Where(x => x > threshold);
    }
}

This single block now works with int, double, decimal, or any numeric type implementing INumber<T>.

Extension Properties

Another huge improvement is the ability to define extension properties.

For example, you can now easily add an IsEmpty property to your collection:

csharp
public static class EnumerableExtensions
{
    extension<T>(IEnumerable<T> source)
    {
        public bool IsEmpty => !source.Any();
    }
}

Now you can use it just like any native property:

csharp
var numbers = new List<int> { 1, 2, 3 };
Console.WriteLine(numbers.IsEmpty); // Output: False

This is definitely a nice feature that will make our code more expressive and readable.

Conclusion

Extension members in C# 14 build on extension methods and add properties and other member kinds too.

You declare the extended type in one extension block and keep related methods and properties together. When you need generics, you write the constraint once in that block instead of repeating it everywhere.

Extension properties let helpers like IsEmpty read like normal properties when you use them.

If you want to check out examples I created, you can find the source code here:

Source Code

I hope you enjoyed it. Subscribe and get a notification when a new blog is up!

Subscribe

Stay tuned for valuable insights every Thursday morning.