我正在尝试编写一个关于数字类型的扩展方法,以便在我正在构建的流畅测试框架中使用。基本上,我想这样做:
public static ShouldBeGreaterThan<T>(this T actual, T expected, string message)
where T : int || T: double || etc...
只是
where T : struct
不行,因为它也会匹配 string
和 bool
,并且可能还有其他我忘记的东西。我可以做些什么来仅匹配数字类型吗? (特别是实现 >
和 <
运算符的类型,因此我可以比较它们......如果这意味着我也匹配日期,那并不重要 - 扩展仍然会按照我的预期进行。 )
IComparable
接口,这使您可以访问 CompareTo
方法,因为该接口允许您回答问题 ShouldBeGreaterThan
。
数字类型将实现该接口,并且它也适用于字符串这一事实不应该让您感到那么困扰。
编辑:
INumber<TSelf>
- 顺便说一句,该接口继承自 IComparable
,但实际上会排除例如string
类型。此外,该接口还继承自 IComparisonOperators
接口,它将为您提供您期望的所有运算符 (<, <=, >=, >, ==, !=
)
where T : struct,
IComparable,
IComparable<T>,
IConvertible,
IEquatable<T>,
IFormattable
这是我能得到的最接近数字约束的值。所有的数字类型都实现了这5个接口,但是IFormattable不是bool实现的,而字符串是引用类型,所以它们不适用。
还有一些其他东西可以实现这些 - 例如 DateTime,所以它并不真正符合要求,但会阻止许多您不想要的实例化。
public static bool IsGreaterThan<T>(this T actual, T comp) where T : IComparable<T>
{
return actual.CompareTo(comp) > 0;
}
如果需要,您也可以添加结构约束。
很难仅限于数字,因为没有像
INumeric
这样常见的东西可以用作过滤器。实际上,我怀疑这里最简单的方法是not坚持约束,并在方法内部使用Comparer<T>.Default.Compare
。
此内置类型支持泛型
IComparable<T>
和非泛型 IComparable
,并通过 Nullable<T>
支持引用类型、值类型和提升用法。
要了解完整的 operator 用法,请查看 MiscUtil 的
Operator
类 和 GreaterThan
等,如果您真的想要使用运算符(而不是接口),这可能会很有用。它还提供对其他运算符的访问,例如 Add
等。
Stackoverflow 上充斥着此类问题。 看看这个搜索。 C# 不支持定义受数字约束的泛型类型的方法。遗憾的是,最好的选择是在所有对象上实现扩展方法,并根据类型进行切换,或者为整数、双精度、浮点数等创建一组方法。
此解决方法可能会有所帮助:使用策略的解决方法。它提供编译时安全性。