DEV Community

Cover image for Extension Members: My New Favourite Feature in C# 14
Grant Riordan
Grant Riordan

Posted on

Extension Members: My New Favourite Feature in C# 14

The release candidate of .Net10 was released on the 9th September [2025], which comes with C# 14, and with that comes one of my favourite features, Extension Members

The Concept

The new extension keyword defines an extension scope; a block where you declare which type your extension methods apply to. All methods inside that scope automatically extend the specified type.

Before and After

Current Implementation

So up until C# 14 you would declare an extension method like this:

public static class StringExtensions
{
    public static string ToTitleCase(this string input) =>
         CultureInfo.CurrentCulture.TextInfo.ToTitleCase(input.ToLower());
}
Enter fullscreen mode Exit fullscreen mode

It can be cumbersome, and to some junior developers it may not be obvious that the method is an extension method. You would have to know that static + this = extension.

The New Way

Firstly you declare your extensions scope using the new extension keyword:

public static class StringExtensions
{
   extension(string text)
   {
      // extension methods go here
   }
}
Enter fullscreen mode Exit fullscreen mode

This replaces the (this string text) syntax, now all methods within this block apply to this type. The new syntax makes declaring all your extensions for this type much cleaner and tidier.

Let's add some basic extensions to show you the concepts:

public static class StringExtensions
{

    extension(string text)
    {
        public string ToTitleCase() =>
            CultureInfo.CurrentCulture.TextInfo.ToTitleCase(text.ToLower());

        public bool IsPalindrome() =>
            text.SequenceEqual(text.Reverse());
    }

}
Enter fullscreen mode Exit fullscreen mode

The examples above show just how easy it is to now declare multiple extension methods on the same type, because we can just use the scoped variable text , rather than having to redefine it each time with this.

Shorter Method Declarations:

// before
public static class DateTimeExtensions
{
    public static bool IsWeekend(this DateTime date) =>
        date.DayOfWeek is DayOfWeek.Saturday or DayOfWeek.Sunday;
}

//after
public static class DateTimeExtensions
{
    extension(DateTime date)
    {
        public bool IsWeekend() =>
            date.DayOfWeek is DayOfWeek.Saturday or DayOfWeek.Sunday;

        public bool IsBusinessHours() =>
            date.Hour is >= 9 and < 17 && !date.IsWeekend();
    }
}
Enter fullscreen mode Exit fullscreen mode

Extensions Can Easily Be Grouped

Before C# 14, you might see a single Helpers class like this:

public static class Extensions
{
    // for DateTime
    public static bool IsWeekend(this DateTime date) {  }

    // for collections
    public static bool HasDuplicates<T>(this IEnumerable<T> items) {  }

    // for strings
    public static string ToTitleCase(this string text) {  }

    // and so on...
}
Enter fullscreen mode Exit fullscreen mode

The problem with this approach:

Hard to maintain– Over time, these Helpers classes can balloon to 500–1,000+ lines of mixed methods, making it difficult for developers to find what they need. – One file can contain extensions for multiple unrelated types.

Before C# 14 After C# 14
Helpers.cs (mixed types) Extensions.cs (type-scoped)
- DateTime extensions - extension(DateTime date) { … }
- IEnumerable extensions - extension(IEnumerable items) { … }
- string extensions - extension(string text) { … }
- Random other methods … neatly grouped per type

Let's take a look how the code may look with the new groupings:

public static class Extensions
{
    extension(DateTime date)
    {
        public bool IsWeekend() {...}

        public bool IsBankHoliday() {...}

        public bool FormatIsoDate() {...}
    }

    extension(IEnumerable<T> items)
    {
        public bool HasDuplicates() {...}
    }

    extension(string text)
    {
        public string ToTitleCase() {...}
    }
}
Enter fullscreen mode Exit fullscreen mode

That means:

*Natural grouping by type *– all string extensions must sit inside the extension(string) scope, all DateTime ones inside extension(DateTime).

Prevents mixing unrelated stuff– you literally cannot write a string extension in the DateTime scope. The compiler enforces it.

Cleaner discoverability– IDEs and developers now know exactly where to look. If you collapse your editor, you’ll see one extension(string) block, one extension(DateTime) block, instead of a 500+ line god like class of random extensions.

Before, people dumped everything into Helpers.cs.

Now, even if your team of developers decides to keep a single file called Extensions.cs, the syntax itself enforces organisation by type, so it’s much less likely to create a “misc soup” of extensions scattered around the file.

We Now Have Extension Properties !

New in C#14 we no longer just have to have extension methods, we can now utilise extension properties. Meaning without huge refactors, or updating multiple places you can easily add Extension properties, to compute results.

For example:

extension<T>(IEnumerable<T> source)
{
    public bool IsNullOrEmpty => source == null || !source.Any();
}
Enter fullscreen mode Exit fullscreen mode

You now have a IsNullOrEmpty property which will be attached to every IEnumerable type within your code base.

So you can do things like:

    List<string> names = ["Grant Green", "Roger Red", "Bianca Blue"];

    // Before (method style)
    if (names.IsNullOrEmpty())
    {
        Console.WriteLine("No names found!");
    }

    // After C# 14 (property style)
    if (names.IsNullOrEmpty)
    {
        Console.WriteLine("No names found!");
    }
Enter fullscreen mode Exit fullscreen mode

I think you'll agree using a property instead of a method makes the code read like it's part of the type itself. It's cleaner, easier to read, and removes the mental overhead of remembering parentheses for simple checks.

Final thoughts

C# 14’s extension members are a small language change with a big impact!

They enforce better organisation by type, reducing the mess of “miscellaneous helpers” spread across static classes.

Extension properties make your APIs feel more natural, allowing boolean checks and computed values to read like first-class members of the type.

Overall, your code becomes cleaner, more discoverable, and easier for teams to maintain.

While the compiler doesn’t stop you from scattering extensions across multiple classes, using a consistent type-scoped approach helps keep your codebase tidy and readable.

In short: if you frequently write helper methods or utilities, C# 14 extension members are worth adopting — they make your codebase feel more structured and your extensions feel like they belong.

Which types do you most often extend in your projects? I’d love to hear your thoughts in the comments or drop me a follow on twitter/x to hear when I post more articles like this on DevTo and FreeCodeCamp.

Top comments (0)