【问题标题】:Generic function which contains T.TryParse(x, out y)? [duplicate]包含 T.TryParse(x, out y) 的通用函数? [复制]
【发布时间】:2016-02-26 00:07:06
【问题描述】:

有几个功能几乎相同(或者不同的部分可以很容易地使用类型参数来实现)。但是,每个函数调用不同的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 的任何类型)?

【问题讨论】:

标签: c#


【解决方案1】:

这是关于 C# 中基于约束的泛型的痛苦现实之一,您想说您将支持具有所需签名的方法 TryParse 但您正在使用的类型上没有此类接口的任何类型并且无法在它们上添加这样的接口。可以这么说,您还需要一般地引用静态方法(因为TryParse 是该类型的静态方法),这是不幸的。

您真正需要的是 C++ 样式模板,这些模板可作为 C++\CLI 中的托管模板使用,但即使这样也有点复杂,因为使静态方法调用“通用”。 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 文件一样。

【讨论】:

    猜你喜欢
    • 2022-01-08
    • 2021-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-06
    • 2022-07-21
    • 2019-08-30
    • 2021-07-21
    相关资源
    最近更新 更多