利用 C# 14 Extension 特性实现更简单高效的扩展
Intro
C# 14 支持了扩展成员 C# 14 Extensions 来了,我们可以更灵活地扩展了,对于多框架的扩展方法来说可以更加简单,对于方法调用的性能来说也会更加简单,让我们来看一个简单的示例吧
Sample
传统的一个扩展方法可能会这样定义,扩展方法定义如下:
public static class MyExtensions
{
public static string CustomHexStringLower(this byte[] bytes)
{
#if NET9_0_OR_GREATER
return Convert.ToHexStringLower(bytes);
#else
return Convert.ToHexString(bytes).ToLowerInvariant();
#endif
}
//...
}
这里是一个方法将字节数组转换成十六进制的字符串,在 .NET 9 及之后的框架使用新的 Convert.ToHexStringLower 对于之前的框架使用 Convert.ToHexString().ToLowerInvariant()
使用示例:
var bytes = "Hello, World!"u8.ToArray();
Console.WriteLine(bytes.CustomHexStringLower());
我们的示例定义两个框架 net8.0/net10.0
这应该是一个很普遍的用法吧,在 C# 14 里我们就可以使用 extension 来简化了,为 .NET 9.0 以下的框架扩展 Console 类型
public static class MyExtensions
{
#if !NET9_0_OR_GREATER
extension(Convert)
{
public static string ToHexStringLower(byte[] bytes)
{
return Convert.ToHexString(bytes).ToLowerInvariant();
}
}
#endif
}
使用时可以直接使用新的 API 了
var bytes = "Hello, World!"u8.ToArray();
Console.WriteLine(Convert.ToHexStringLower(bytes));
这样我们在旧版本的 .NET 框架中也可以使用新的 API 而且性能会更好一些,尤其是对于高版本框架少一层方法调用,调用堆栈少一些
.NET 8.0 反编译结果:
.NET 10.0 反编译
从上面的反编结果可以清晰地看到新的 extension 方式就简单了很多
执行结果
微软在 .NET 框架里也有一些类似的用法,比如针对 exception throw helpers ,可以参考 PR:
https://github.com/dotnet/runtime/pull/114644
namespace System;
/// <summary>Provides downlevel polyfills for static methods on Exception-derived types.</summary>
internal static class ExceptionPolyfills
{
extension(ArgumentNullException)
{
public static void ThrowIfNull([NotNull] object? argument, [CallerArgumentExpression(nameof(argument))] string? paramName = null)
{
if (argument is null)
{
ThrowArgumentNullException(paramName);
}
}
}
[DoesNotReturn]
private static void ThrowArgumentNullException(string? paramName) =>
throw new ArgumentNullException(paramName);
}
ThrowHelper 也就不需要了
使用这种方式之后我们去做一些低版本框架的 polyfill 的时候就会更简单更高效,如果你也有针对低版本框架的类库型应用也可以尝试以下新的扩展方式来简化一些代码~~
References
-
• https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-14#extension-members -
• https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/extension?WT.mc_id=DT-MVP-5004222 -
• https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/extension-methods?WT.mc_id=DT-MVP-5004222 -
• https://github.com/dotnet/runtime/pull/114644 -
C# 14 Extensions 来了

