基于INumber<T>泛型约束的类如何返回NaN?
在INumber泛型中返回NaN的解决方案
首先要明确:不是所有实现INumber<T>的类型都支持NaN值。比如整数类型(int、long、short等)和decimal本身没有NaN的概念——这些类型的所有实例都是有效的数值,不存在“非数字”的状态,因此对于这类类型,你无法返回NaN,只能抛出异常。
对于支持NaN的类型(如float、double、nfloat等符合IEEE 754标准的浮点类型),可以通过INumberBase<T>接口定义的静态属性T.NaN来获取该类型的NaN值,因为INumber<T>继承了INumberBase<T>。
修改后的Divide类实现
public class Divide<T> where T : INumber<T> { public T Evaluate() { var divisor = Child[1].Evaluate(); if (divisor.CompareTo(T.Zero) == 0) { try { // 尝试返回NaN,不支持的类型会抛出NotSupportedException return T.NaN; } catch (NotSupportedException) { // 针对不支持NaN的类型,抛出除零异常 throw new DivideByZeroException("无法对不支持NaN的类型执行除零操作"); } } var dividend = Child[0].Evaluate(); return dividend / divisor; } }
更精准的类型判断(避免异常捕获)
如果你想提前判断类型是否支持NaN,而不是依赖异常捕获,可以通过类型码来区分:
public class Divide<T> where T : INumber<T> { public T Evaluate() { var divisor = Child[1].Evaluate(); if (divisor.CompareTo(T.Zero) == 0) { var typeCode = Type.GetTypeCode(typeof(T)); return typeCode switch { TypeCode.Single => (T)(object)float.NaN, TypeCode.Double => (T)(object)double.NaN, TypeCode.NFloat => (T)(object)nfloat.NaN, _ => throw new DivideByZeroException("无法对不支持NaN的类型执行除零操作") }; } var dividend = Child[0].Evaluate(); return dividend / divisor; } }
关于无穷大的补充
和NaN一样,无穷大也只有IEEE 754浮点类型支持,你可以用T.PositiveInfinity或T.NegativeInfinity来获取,同样只适用于支持的类型,不支持的类型会抛出异常或需要提前判断。
内容的提问来源于stack exchange,提问作者Dominick
相关产品推荐
相关产品推荐

