有几个功能几乎相同(或者使用类型参数可以轻松实现不同的部分)。但是,每个函数的一个区别是调用不同的TryParse()
函数。
void Fun1<T>(T p) where T : IBase // simplified
{ ......
int x;
if(int.TryParse(p.S, out x)) { .... }
}
void Fun1<T>(T p) where T : IBase
{ ......
decimal x;
if(decimal.TryParse(p.S, out x)) { .... }
}
......
如何为这些函数创建一个带有int,decimal,double,short,...(带方法TryParse
的任何类型)的类型参数的泛型方法?
答案 0 :(得分:3)
这是关于C#中基于约束的泛型的痛苦现实之一,你想说你将支持任何具有所需签名方法TryParse
的类型,但是类型上没有这样的接口正在使用,无法在其上添加此类接口。你还需要一般性地引用一个静态方法,因为(TryParse
是一种类型的静态方法),这是很不幸的。
这里你真正需要的是C ++样式模板,这些模板在C ++ \ CLI中作为托管模板提供,但即便如此,因为要进行静态方法调用&#34; generic&#34;。 C ++模板魔法可以帮到你,但为了保存戏剧,你可以使用一个好的旧T4模板来模仿C ++必须做的事情减去任何额外的模板元编程。
我创建了以下T4模板:
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".cs" #>
<#
List<string> types = new List<string>() { "decimal", "int" };
foreach (string t in types)
{
#>
void Fun1(<#=t#> p) // simplified
{ //......
<#=t#> x;
if(<#=t#>.TryParse(p.S, out x)) { /*....*/ }
}
<#
}
#>
这给了我以下输出:
void Fun1(decimal p) // simplified
{ //......
decimal x;
if(decimal.TryParse(p.S, out x)) { /*....*/ }
}
void Fun1(int p) // simplified
{ //......
int x;
if(int.TryParse(p.S, out x)) { /*....*/ }
}
我认为这与你正在寻找的大致相同。我认为在你的情况下,这是最简单的解决方案,可以避免所有的反射戏剧或下载到托管模板(仍然可能是静态方法调用的反射)或者甚至更深入到C ++。 T4方法输出一个.cs文件,因此编译器会像项目中任何其他.cs文件一样警告您有关问题。