DEV Community

Cover image for C# 14 extension blocks
Karen Payne
Karen Payne

Posted on

C# 14 extension blocks

Introduction

Learn about C# 14 extension blocks while targeting NET Core 9. This can be done by adding the following to the project file.

shows part of a project file

What are convention extension methods?

C# extension methods let you add new methods to existing types without modifying their source code or creating subclasses. They’re defined as static methods in a static class, with the first parameter prefixed by this to indicate the type being extended. Once in scope, they look and feel like native instance methods, which makes code more readable and expressive.

extension blocks benefits

Unlike the old syntax, extension blocks allow you to define extension properties, operators, and static members for a type.

Old syntax

public static class StringExtensions
{
    public static string CapitalizeFirstLetter(this string sender)
        => string.IsNullOrEmpty(sender) ? sender : $"{char.ToUpper(sender[0])}{sender[1..].ToLower()}";
}
Enter fullscreen mode Exit fullscreen mode

New syntax

public static class StringExtensions
{
    extension(string sender)
    {
        public string CapitalizeFirstLetter()
            => string.IsNullOrEmpty(sender) ? sender : $"{char.ToUpper(sender[0])}{sender[1..].ToLower()}";

    }
}
Enter fullscreen mode Exit fullscreen mode

Usage

string firstName = "KAREN";
string lastName = "SMITH";

var fullName = $"{firstName.CapitalizeFirstLetter()} {lastName.CapitalizeFirstLetter()}";
Enter fullscreen mode Exit fullscreen mode

The "receiver" (the instance you are extending) is once for the entire block, making the code cleaner and more organized.

shows receiver example

public static class BoolExtensions
{
    extension(bool value)
    {
        public string IsEmpty() =>
            value switch
            {
                true => "Yes is empty",
                _ => "No is not empty"
            };

        public string ToYesNo() =>
            value switch
            {
                true => "Yes",
                _ => "No"
            };
    }
}
Enter fullscreen mode Exit fullscreen mode

Inside the block, members are declared like regular instance members. You don't need to repeat the this parameter for every method.

Not supported prior to C# 14

Static operators can be used with C# 14, but not in preview.

public static class EnumerableExtensions
{
    // The generic T is defined at the block level
    extension<T>(IEnumerable<T> first)
    {
        // Extension Operator
        // Note: At least one parameter must match the extended type (IEnumerable<T>)
        public static IEnumerable<T> operator +(IEnumerable<T> left, IEnumerable<T> right)
            => left.Concat(right);

        // Extension Compound Assignment (C# 14 feature)
        // This allows 'collection += item' behavior
        public static IEnumerable<T> operator +(IEnumerable<T> left, T item)
            => left.Append(item);
    }
}
Enter fullscreen mode Exit fullscreen mode

Sample usage

var list1 = new[] { 1, 2 };
var list2 = new[] { 3, 4 };
var combined = list1 + list2; // Yields { 1, 2, 3, 4 }
Enter fullscreen mode Exit fullscreen mode

Rules for Extension Operators

  • Static Context: Like standard operators, extension operators must be declared public static.
  • Identity Rule: One of the operator's parameters must be identity-convertible to the type being extended (e.g., if you extend T[], one parameter must be T[]).
  • Compound Assignments: C# 14 also introduces user-defined compound assignment operators (like +=), which can now be implemented as extensions.

Constrained Generic Operators

You can combine extension operators with Generic Math constraints (e.g., INumber) to perform arithmetic on collections of numbers.

public static class NumericExtensions
{
    extension<T>(IEnumerable<T> source) where T : INumber<T>
    {
        public IEnumerable<T> OnlyPositive => source.Where(x => x > T.Zero);
    }
}
Enter fullscreen mode Exit fullscreen mode

Article source code

Source code

console project structure

Summary

Using extension blocks means a developer has cleaner code, both for readability and maintenance, than before C#14. When using extension blocks in a team of developers, make sure to explain them to team members, especially developers who tend not to work with conventional extension methods.

Top comments (0)