With the latest preview: .NET 10 preview 3, we did get an overhaul on extensions. It might enable some nice tricks in the future.
Extensions
The new feature called Extension members is basically extending the already existing extensions and bringing them to the next level.
If we had this in the pre-C# 14 world:
public static class Extensions
{
public static IEnumerable<int> WhereGreaterThan(this IEnumerable<int> source, int threshold)
=> source.Where(x => x > threshold);
}
We can achieve the same with this new syntax:
public static class Extensions
{
extension(IEnumerable<int> source)
{
public IEnumerable<int> WhereGreaterThan(int threshold)
=> source.Where(x => x > threshold);
public bool IsEmpty
=> !source.Any();
}
}
As you can see, we can group similiar things easier together. Until now, this is basically a new syntax but we didn't achieve anything new. But that changes:
Extending with static methods
The new cool thing is that you can new static methods on top of a type:
extension<T>(List<T>)
{
public static List<T> Create()
=> [];
}
Now, you can call:
var foo = List<int>.Create();
Okay, so far, so good. But what can we do with that? Well there are two cool features that might be possible (they are not right now).
Adding static operators to 3rd party types
We can easily add operator
s to existing 3rd party types. They are defined as static invocations on a type, so we can do something like this:
public class MyObject(int number)
{
public int Number { get; } = number;
}
public static class Extensions
{
extension(MyObject)
{
public static int operator +(MyObject x, MyObject y)
{
return x.Number + y.Number;
}
}
}
Remember MyObject
itself doesn't define any +
but the extension does. So we would be allowed to do something like:
var m1 = new MyObject(2);
var m2 = new MyObject(3);
Console.WriteLine(m1.Add(m2));
Adding new collection expressions on unsupported types
Basically, what we want is to allow the [1,2,3]
syntax for types that currently don't support that. I took as an example IReadOnlySet<T>
. If you are not aware what collection expressions are or how to build them for your own types: https://andrewlock.net/behind-the-scenes-of-collection-expressions-part-5-adding-support-for-collection-expressions-to-your-own-types/
So, while currently not working, we might have a chance that we can equip 3rd party types as such:
IReadOnlySet<int> set = [1, 2, 3];
[CollectionBuilder(typeof(Extensions), nameof(Extensions.Create))]
public static class Extensions
{
extension<T>(IReadOnlySet<T>)
{
public IReadOnlySet<T> Create(ReadOnlySpan<T> items)
{
return new HashSet<T>(); // Here something useful
}
}
}
The problem is that the compiler doesn't look on any other type than the target type for the attribute - so while the extension does compile, it does not create the effect I was aiming for. Let's see in the future which cool things we can enable with this new language feature.