能否合并具有不同约束的.NET 7泛型数学除法函数?
解决方案
你遇到的两个核心问题:
- 类型判断逻辑错误:
typeof(T) == typeof(IFloatingPoint<>)是拿具体类型和开放泛型接口做比较,永远不会相等,正确的做法是检查T是否实现了封闭的IFloatingPoint<T>接口。 - 编译器无法在条件分支内推断T的接口实现:即使判断T是浮点类型,编译器也不会自动将T视为
IFloatingPoint<T>,因此无法直接访问T.Floor。
以下是几种可行的合并方案:
方案一:无装箱高性能实现(推荐)
利用辅助泛型方法+Unsafe.As实现类型转换,既满足编译器的泛型约束检查,又避免装箱拆箱的性能损耗:
using System.Runtime.CompilerServices; using System.Numerics; static T Divide<T>(T dividend, T divisor) where T : INumber<T> { if (typeof(IFloatingPoint<T>).IsAssignableFrom(typeof(T))) { // 安全转换类型以匹配辅助方法的泛型约束 return FloatingPointDivide(Unsafe.As<T, T>(dividend), Unsafe.As<T, T>(divisor)); } return dividend / divisor; // 仅针对浮点类型的分支逻辑 static TFloat FloatingPointDivide<TFloat>(TFloat dividend, TFloat divisor) where TFloat : IFloatingPoint<TFloat> { return TFloat.Floor(dividend / divisor); } }
方案二:简洁实现(适合低频率调用)
使用动态类型简化代码,但会带来运行时类型解析的性能开销:
using System.Numerics; static T Divide<T>(T dividend, T divisor) where T : INumber<T> { dynamic div = dividend; dynamic divs = divisor; var divisionResult = div / divs; if (typeof(IFloatingPoint<T>).IsAssignableFrom(typeof(T))) { return T.Floor(divisionResult); } return divisionResult; }
方案三:反射实现(不推荐)
依赖反射调用Floor方法,性能最差,仅在特殊场景下使用:
using System.Reflection; using System.Numerics; static T Divide<T>(T dividend, T divisor) where T : INumber<T> { var divisionResult = dividend / divisor; var floatingPointInterface = typeof(IFloatingPoint<T>); if (floatingPointInterface.IsAssignableFrom(typeof(T))) { var floorMethod = floatingPointInterface.GetMethod(nameof(IFloatingPoint<T>.Floor), BindingFlags.Public | BindingFlags.Static); if (floorMethod != null) { return (T)floorMethod.Invoke(null, new object[] { divisionResult }); } } return divisionResult; }
方案对比
- 方案一:性能最优,无额外开销,适合性能敏感的高频调用场景。
- 方案二:代码最简洁,但动态类型会导致运行时开销,适合调用频率较低的场景。
- 方案三:依赖反射,性能最差,仅作为前两种方案的备选。
内容的提问来源于stack exchange,提问作者Matthew Layton
相关产品推荐
相关产品推荐

