Interfaces have always been a way to define a contract that classes must implement. Since C# 8.0 they could also contain static members with implementations, but there was no way to require implementing types to provide a static member.
In C# 11.0, you can now define static abstract or virtual members on an interface and call them through a type parameter.
Code
csharp
public interface IConcatable<T> where T : IConcatable<T>
{
static abstract T Empty { get; }
static abstract T Concat(T a, T b);
}
static T ConcatAll<T>(IEnumerable<T> items) where T : IConcatable<T>
{
T result = T.Empty;
foreach (var item in items)
result = T.Concat(result, item);
return result;
}csharp
public interface IConcatable<T> where T : IConcatable<T>
{
T Concat(T other);
}
// No way to ask T for an empty value, so the caller must supply one
static T ConcatAll<T>(T empty, IEnumerable<T> items) where T : IConcatable<T>
{
T result = empty;
foreach (var item in items)
result = result.Concat(item);
return result;
}Notes
- This feature is part of the work in enabling generic math support