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());
}
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
}
}
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());
}
}
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();
}
}
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...
}
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() {...}
}
}
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();
}
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!");
}
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)