Extension Members in .NET 10
Reading Time: 2 minutes
Problem
Classic extension methods are useful, but they can become difficult to organize as projects grow.
Common pain points:
- related extension APIs spread across many static classes
- method discovery in IntelliSense is inconsistent
- no natural place for richer extension surface beyond plain methods
- teams overuse utility classes because extension methods feel too limited
When the extension surface area grows, maintainability and discoverability often get worse.
Solution
Use extension members in .NET 10 (C# 14) to define extension APIs in a more structured way.
This gives you a cleaner model for extending existing types while keeping source types untouched.
Practical benefits:
- more cohesive extension design
- easier IntelliSense discovery for grouped members
- cleaner API evolution than scattered helper methods
- better readability for domain-oriented extensions
Keep using classic extension methods where simple, but prefer extension members when you need a broader, intentional extension surface.
Description
1) Before: classic extension method style
public static class StringExtensions
{
public static bool IsNullOrWhiteSpaceEx(this string? value)
=> string.IsNullOrWhiteSpace(value);
public static string OrDefault(this string? value, string fallback)
=> string.IsNullOrWhiteSpace(value) ? fallback : value;
}
This works, but the approach does not scale well when you add many related APIs.
2) Extension members style in .NET 10
public static class StringMemberExtensions
{
extension(string? value)
{
public bool IsMissing()
=> string.IsNullOrWhiteSpace(value);
public string OrDefault(string fallback)
=> string.IsNullOrWhiteSpace(value) ? fallback : value;
}
}
Usage remains natural:
var name = input.OrDefault("anonymous");
var missing = input.IsMissing();
3) Domain-focused extension members
Extension members are especially useful for domain readability.
public readonly record struct Money(decimal Amount, string Currency);
public static class MoneyExtensions
{
extension(Money money)
{
public bool IsZero() => money.Amount == 0m;
public Money Add(Money other)
{
if (!string.Equals(money.Currency, other.Currency, StringComparison.Ordinal))
throw new InvalidOperationException("Cannot add different currencies.");
return money with { Amount = money.Amount + other.Amount };
}
}
}
This keeps domain intent readable without modifying the original type.
4) Guidance for production use
- Keep extension members focused on behavior that feels native to the target type.
- Avoid adding behavior that surprises callers or hides expensive operations.
- Prefer explicit naming over overly clever shorthand.
- Group related members in feature-oriented files to improve maintainability.
Summary
Extension members in .NET 10 improve how teams design and organize extension APIs.
Compared with scattered utility-style extension methods, they provide a more cohesive and discoverable approach for building expressive helper APIs around existing types.
Use them when extension behavior grows beyond a few helper methods, especially in domain-heavy codebases where readability and API clarity matter.
References
- Microsoft Docs: Extension Members (C#)