2017-08-04 92 views
2

虽然这样做对我们的应用一些分析,我发现这个代码:原始类型转换,无需拳击

public TOut GetValue<TIn, TOut>(Func<TIn> getter) 
{ 
    var value = getter(); 

    // Do some stuff with the value 

    return (TOut)Convert.ChangeType(value, typeof(TOut)); 
} 

TInTOut的是int,double或字符串。

由于使用int或double时的装箱,这在分析会话中显示为堆分配的重要来源。输入值Convert.ChangeType被装箱,因为该方法需要一个对象,并且出于同样的原因返回值被装箱。

我想优化此代码,因为此方法用于高吞吐量服务,这种分配是禁止的。理想情况下,我会将该方法改写为非通用方法,但API被各个团队广泛使用,重构此类规模需要数月时间。与此同时,我正试图缓解这个问题,并找到一种方法来改善这种情况,而无需更改API合同。然而,我一直在这方面挣扎了一段时间,还没有找到解决办法。

你知道一个方法,甚至丑陋的,以处理int - > double和double - > int转换没有拳击,给定的方法合同?请注意,我无法更改参数,但我可以添加通用约束(例如where TIn : IConvertible,但这对我没有多大帮助)。

+3

换句话说,你想要通用的'ChangeType'?您可以使用[“switch/case”](http://referencesource.microsoft.com/#mscorlib/system/convert.cs,348)来查看您关心的所有类型,或者使用盒装版本。 – Sinatr

+0

也许看看[.NET参考资源的Convert.ChangeType](http://referencesource.microsoft.com/#mscorlib/system/convert.cs,dc591cb7008278c6)将有助于了解它的功能,也许可以让你为您的特定场景创建一个更短/更快/更高效的方法。 –

回答

1

如果您只需要专注一对夫妇的转换,我认为以下工作,并且不承担任何每个呼叫分配:

private static int FromDouble(double other) 
    { 
     return (int)other; 
    } 
    private static double FromInt(int other) 
    { 
     return (double)other; 
    } 

    private static Func<double, int> di = FromDouble; 
    private static Func<int, double> id = FromInt; 
    public TOut GetValue<TIn, TOut>(Func<TIn> getter) 
    { 
     var value = getter(); 

     // Do some stuff with the value 

     if (typeof(TIn) == typeof(int) && typeof(TOut) == typeof(double)) 
     { 
      var gf = (Func<TIn, TOut>)(object)id; 
      return gf(value); 
     }else if (typeof(TIn) == typeof(double) && typeof(TOut) == typeof(int)) 
     { 
      var gf = (Func<TIn, TOut>)(object)di; 
      return gf(value); 
     } 

     return (TOut)Convert.ChangeType(value, typeof(TOut)); 
    } 

有一对夫妇进一步调整的可能这个进行, 当然。

+0

我没有想到要代表一个代表,这很聪明。谢谢! –