C#  

What you need to know about Extension Members in C#

Extension methods have been around in C# for a long time. They allow you to add new methods to existing types without modifying their source code. This is very useful when working with types from frameworks or libraries you do not own.

However, extension methods have one annoyance: every method must be defined in a static class, and each method must declare the first parameter with the this modifier. When you write several extension methods for the same type, your code starts to feel repetitive.

Extension Members, were introduced to solve this problem by allowing you to group extension methods inside an extension block tied to a specific type.

What Are Extension Members?

Extension members let you define an extension scope like this:

extension System.String
{
    // instance extension
    int WordCount() => this.Split(' ').Length;

    // static extension
    static bool IsNullOrEmpty(string? value) => string.IsNullOrEmpty(value);
}

Before vs After

Before (Classic Extension Methods)

public static class StringExtensions
{
    public static int WordCount(this string text)
    {
        return text.Split(' ').Length;
    }
}

After (Extension Block)

extension System.String
{
    int WordCount() => this.Split(' ').Length;
}

Example

extension System.String
{
    bool IsLong() => this.Length > 20;
    static string? EmptyIfNull(string? value) => value ?? string.Empty;
}

Usage

string message = "Hello World";
bool isLong = message.IsLong();
string result = string.EmptyIfNull(null);

Extension Members Priority Rule

Extension members are always lower priority than the type's existing members. Meaning: if the type already defines a method with the same name, the type's method is used.

Example

extension System.String
{
    string ToUpper() => "Extension ToUpper called";
}

var text = "hello";
Console.WriteLine(text.ToUpper());

Output

HELLO

=> The built-in string.ToUpper() wins.

Extension Members in C# 14 – What Changed?

C# 13 introduced the extension block, which allows you to define methods and static helpers on existing types more naturally. C# 14 takes this further by allowing you to define more kinds of members, not just methods.

Example: Extension Property (C# 14)

extension System.String
{
    int WordCount => this.Split(' ', StringSplitOptions.RemoveEmptyEntries).Length;
}

Usage

string text = "Hello world from C#";
Console.WriteLine(text.WordCount); // 4

No parentheses. It behaves exactly like a read-only property.

Example: Extension Indexer (C# 14)

extension System.String
{
    char this[Index index] => this[index];
}

Usage

string s = "Hello";
Console.WriteLine(s[^1]); // o

This allows idiomatic slicing without writing your own helper code.