为什么编译器不接受这个通用函数?

时间:2011-08-20 22:32:03

标签: c#-4.0

public static T clipGN<T>(this T v, T lo, T hi) where T : decimal,double
{ return Math.Max(lo, Math.Min(hi, v)); }

给出了第二行:

Argument 1: cannot convert from 'T' to 'decimal'

为什么呢?我认为满足T约束的两种类型都可以转换为十进制。

BTW,可以在答案中找到可接受的替代编码: How should one best recode this example extension method to be generic for all numeric types?

2 个答案:

答案 0 :(得分:1)

你不需要泛型。虽然“DRY”的概念使得编写可以适用于所有类型的单个函数的想法,但这种情况下,您最好为每种数字类型设置谨慎的函数。所有数字类型都是已知的,列表不是太大;无论如何,有可能是你实际上不会使用的数字类型。如果你真的(无论出于何种原因)想要一个函数,那么你唯一真正的选择就是你链接到的IComparable选项,这会导致对数字参数造成限制的不幸(和不必要的)后果。

话虽如此,您的问题是您不能拥有T : decimal, double,因为这意味着T必须 decimaldouble (这是不可能的),而不是它可以是一个。

此外,由于这就是这个函数所做的一切,我可能无论如何都不会调用Math.MaxMath.Min函数。用这样的方式编写函数可能就是这么简单,如果不是稍微清楚一点:

public static decimal ClipGN(this decimal v, decimal lo, decimal hi)
{
    return v <= lo ? lo : v >= hi ? hi : v;
}

您应该能够逐字复制此代码(当然,除了返回和参数类型之外)。

答案 1 :(得分:1)

我自己尝试编译代码并且自己收到以下错误:

  

'double'不是有效的约束。用作约束的类型必须   是一个接口,一个非密封类或一个类型参数。 (CS0701)

decimal相同。这表明,decimaldouble都不允许约束类型参数T,因为可以满足该约束的唯一类型本身(它与制作非泛型重载没有区别,取而代之的是T使用decimaldouble)。即使单独允许它们约束T(它们不是),仍然不允许组合约束,因为任何类型都不能同时为decimaldouble

如果约束条件为where T : IComparable<T>,则不同,其中两种类型以及其他类型都可以满足该约束条件。