← Back to all posts

Extension Members in .NET 10

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