将通用参数传递给非通用方法

3

我正在尝试创建一个方法,可以将可空类型四舍五入到指定的小数位。理想情况下,我希望这是一个通用的方法,以便我可以像使用 Math.Round() 一样使用它来处理Double和Decimal。

我编写的代码无法编译,因为该方法无法(可以理解)解析,不知道该调用哪个重载。如何实现此功能?

internal static T? RoundNullable<T>(T? nullable, int decimals) where T : struct
{
    Type paramType = typeof (T);

    if (paramType != typeof(decimal?) && paramType != typeof(double?))
        throw new ArgumentException(string.Format("Type '{0}' is not valid", typeof(T)));

    return nullable.HasValue ? Math.Round(nullable.Value, decimals) : (T?)null; //Cannot resolve method 'Round(T, int)'
 }

+1 有趣,不过直接编写两个重载可能更容易。 - Rup
为什么不使用两种方法,一种用于十进制数,另一种用于双精度数?这样可以避免强制转换,代码也会更清晰。 - sll
2个回答

7
这怎么实现?
个人来看,我会直接移除你的通用方法。它只对两种类型参数有效,最好拆成两个重载方法:
internal static double? RoundNullable(double? nullable, int decimals)
{
    return nullable.HasValue ? Math.Round(nullable.Value, decimals)
                             : (double?) null;
}

internal static decimal? RoundNullable(decimal? nullable, int decimals)
{
    return nullable.HasValue ? Math.Round(nullable.Value, decimals)
                             : (decimal?) null;
}

如果你一定要使用通用版本,可以按照Dave的回答来有条件地调用它,也可以直接使用反射来调用它,或者在使用C# 4和.NET 4时使用dynamic


谢谢 - 我确实想到了这一点,只是觉得使用提供给我们的功能(泛型)会很好。 - m.edmondson
1
@m.edmondson:不,这是对提供的功能的滥用...因为它不是一种真正的通用方法;即使您指定的约束条件也无法真正捕获其受限性。这是一种仅适用于两种特定类型的方法,仅此而已。 - Jon Skeet
谢谢您 - 我确实有一种烦人的感觉,这将是答案。 - m.edmondson
T 的使用在哪里?我认为这个方法可以不用泛型来编写? - Asif Mushtaq
@Asif:抱歉,是的 - 我的意思是它不应该是通用的,我在转换中错过了那一部分。 - Jon Skeet

2

考虑到你已经在进行类型检查,只需在代码流程中使用它:

if (paramType == typeof(decimal?))
...
    Math.Round((decimal)nullable.Value, decimals)
else if(paramType == typeof(double?))
    Math.Round((double)nullable.Value, decimals)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接