包含T.TryParse(x,out y)的通用函数?

时间:2016-02-26 00:07:06

标签: c#

有几个功能几乎相同(或者使用类型参数可以轻松实现不同的部分)。但是,每个函数的一个区别是调用不同的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的任何类型)的类型参数的泛型方法?

1 个答案:

答案 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文件一样警告您有关问题。