Here a simple scenario: You have a StringComparer and you want to add your own comparer to the mix - for example a "natural sort" order, so "file2" sorts before "file10" instead of after.
With C# 14 we can extend the family and make it feel natural!
A new comparer
So we want to add and use something like:
public class NaturalSortComparer : StringComparer
{
public override int Compare(string? x, string? y) => ...
public override bool Equals(string? x, string? y) => ...
public override int GetHashCode(string obj) => ...
}
Pre C# 14
Before C# 14, "extending" a type meant extension methods - so we can only do things like:
public static class StringComparerExtensions
{
public static StringComparer NaturalSort(this StringComparer comparer) => new NaturalSortComparer();
}
Which then feels odd to use: StringComparer.Ordinal.NaturalSort();. Hmm not great. If we have a look at the other folks in the family: StringComparer.OrdinalIgnoreCase and so on, we are far away!
Alternatively, we could do is a separate class:
public static class NaturalSort
{
public static StringComparer Instance { get; } = new NaturalSortComparer();
}
// Usage:
var files = Directory.GetFiles(path)
.OrderBy(f => f, NaturalSort.Instance);
C# 14
C# 14 extension blocks can add static members too, not just methods but properties
public static class StringComparerExtensions
{
extension(StringComparer)
{
public static StringComparer NaturalSort => new NaturalSortComparer();
}
}
With this we can now use it as we want to (as in: As I want to!):
var files = Directory.GetFiles(path)
.OrderBy(f => f, StringComparer.NaturalSort);
Amazing! Steven over and out.