C# 11 和 .NET 7 支持泛型解析

原文链家:https://www.infoq.com/news/2022/11/IParsable/

译文

.NET中一个基础的设计理念就是静态解析方法,几乎每个可以从字符串表示中实例化的类都有一个,然而在C# 11和.NET 7之前,还没有办法创建适应这种情况的接口。

最根本的问题是在这之前抽象接口(例如interface关键字)就不支持静态方法。这不是C#的限制,在引入"Static Abstract Methods in interfaces"功能之前CLR本身就不支持这个功能。
与接口方法一样,静态抽象方法可以有一个默认的实现,不过也有一些限制。

在接口中声明的静态虚拟和静态抽象方法没有类似于在类中声明的虚拟或抽象方法的运行时调度机制。相反,编译器使用编译时可用的类型信息,因此静态虚拟方法几乎只在泛型接口中声明。

今天我们要讨论的示例是IParsable 接口。 它提供两个方法Parse 和 TryParse,二者都接收一个string和IFormatProvider。
要访问他们,你需要一个泛型帮助方法。例如:

static T Parse<T>(string s, IFormatProvider? provider)
    where T : IParsable<T>
{
    return T.Parse(s, provider);
}

传输一个类型参数来调用:

var a = Parse<int>("4", null);

如果你不准备升级到.net 7 , 你可以使用反射来模拟:

static T Parse<T>(string s, IFormatProvider? provider)
{
    //error handling omitted for clarity
    var type = typeof(T);
    var method = type.GetMethod("Parse", BindingFlags.Static | BindingFlags.Public, new[] { typeof(string), typeof(IFormatProvider) });
    var result = (T)method!.Invoke(null, new object?[] { s, provider })!;
    return result;
}

你可以使用与IParsable 相同的方式调用此方法。但这种技术的风险是没有编译时安全性。
如果类型T没有 Parse方法或者此方法参数设置错误,编译器是无法检测到的。

对于性能有要求的代码, 可以考虑使用ISpanParsable接口,通过使用 Span 而不是 String通常可以避免内存分配。

你可能感兴趣的:(C/C++/C#,java,开发语言,c#)