C# 13 new feature: Extension types

One of the features demonstrated by Mads Torgersen and Dustin Campbell’s in the "What’s new in C#" talk at the Microsoft Build 2024 that I really like is the introduction of the extension types.

Extensions methods are allowed since C# 3 and are widely used by the .NET developers. Their main objective is to allow the developers to add some methods to a type. It's useful if you don't want to modify the type or, in most of the case of the extension usage, if you don't have access to the underlying code. LINQ is an example of a set of extension methods on IEnumerable.

If extensions methods are very usefull and widely used, they have some limitations. First you can only add methods, you cannot add properties or other members than methods. Secondly, all the extensions methods have to be static. C# 13 introduces a new version of extensions methods called Extension types that takes the next step. With extension types you can add methods to a type but also any other member. The members you add can be static but also instance, even if instance extension types cannot hold state. Finaly, extension types can be implicit (will be apply to all occurrences of the underlying type) or explicit (you will have to explicitly convert the underlying type to the extension type you want to use).

Let's see what it looks like.

Assume we use this code we can't change:


  public enum MusicInstrumentsEnum
{
    Guitar = 1,
    BassGuitar = 2,
    Drum = 3
}

public class Musician()
{
    public required string FirstName { get; init; } 
    public required string LastName { get; init; }
    public required Band Band { get; init; } 
    public MusicInstrumentsEnum? Instrument { get; init; }
    public required bool IsSinger { get; init; } 
}

// It's pretty reductive about music but it's just for the example!
public class Band()
{
    public required string Name { get; init; }
    public required IEnumerable Musicians { get; init; } 
    public required IEnumerable Albums { get; init; }
}

public class Song()
{
    public required string Name { get; init; }
    public required bool ReleasedOnRadio { get; init; }
}

public class Album
{
    public required string Name { get; init; }
    public required IEnumerable Songs { get; init; }
    public required int SalesCount { get; init; }
}

Imagine you want to know if a musician has played on an album which is Gold Record, with extension types you can do it this way:


public implicit extension MusicianExtension for Musician
{
    public bool HasPlayedOnGlodRecordAlbum
        => this.Band
            .Albums
            .Any(album => album.SalesCount >= 500_000);
}

This property would be called as:


if(musician.HasPlayedOnGlodRecordAlbum)
{
   // ...
}

With explicit extensions you can implement other features, like retrive the list of the Gold record albums a musician played on:


public explicit extension GlodRecordMusician for Person
{
    public IEnumerable GoldRecords 
        => this.Band
            .Albums
            .Where(album => album.SalesCount >= 500_000);
}

This property would be called as:


if (musician.HasPlayedOnGlodRecordAlbum)
{
    GlodRecordMusician glodRecordMusician = musician;
    IEnumerable albums = glodRecordMusician.GoldRecords;
}

Extension types are not replacing extension methods introduced in C# 3, it's an add-on, a new tool you can use to simplify your code, or organize it better.

For more information about it or other C# new features, watch the talk What’s new in C#.

May 31, 2024
  • C#
  • Csharp
  • C# 13
  • Expression types