匹配数字类型的通用约束[重复]

问题描述 投票:0回答:6

我正在尝试编写一个关于数字类型的扩展方法,以便在我正在构建的流畅测试框架中使用。基本上,我想这样做:

public static ShouldBeGreaterThan<T>(this T actual, T expected, string message)
    where T : int || T: double || etc...

只是

where T : struct
不行,因为它也会匹配
string
bool
,并且可能还有其他我忘记的东西。我可以做些什么来仅匹配数字类型吗? (特别是实现
>
<
运算符的类型,因此我可以比较它们......如果这意味着我也匹配日期,那并不重要 - 扩展仍然会按照我的预期进行。 )

c# generics numeric
6个回答
68
投票

在这种情况下,您希望将泛型限制为

IComparable
接口,这使您可以访问
CompareTo
方法,因为该接口允许您回答问题
ShouldBeGreaterThan

数字类型将实现该接口,并且它也适用于字符串这一事实不应该让您感到那么困扰。

编辑:

自 .NET 7 起,您还可以考虑限制为

INumber<TSelf>
- 顺便说一句,该接口继承自
IComparable
,但实际上会排除例如
string
类型。此外,该接口还继承自
IComparisonOperators
接口,它将为您提供您期望的所有运算符 (
<, <=, >=, >, ==, !=
)


60
投票
where T : struct, 
          IComparable, 
          IComparable<T>, 
          IConvertible, 
          IEquatable<T>, 
          IFormattable

这是我能得到的最接近数字约束的值。所有的数字类型都实现了这5个接口,但是IFormattable不是bool实现的,而字符串是引用类型,所以它们不适用。

还有一些其他东西可以实现这些 - 例如 DateTime,所以它并不真正符合要求,但会阻止许多您不想要的实例化。


21
投票
public static bool IsGreaterThan<T>(this T actual, T comp) where T : IComparable<T>
{
    return actual.CompareTo(comp) > 0;
}

如果需要,您也可以添加结构约束。


9
投票

很难仅限于数字,因为没有像

INumeric
这样常见的东西可以用作过滤器。实际上,我怀疑这里最简单的方法是not坚持约束,并在方法内部使用
Comparer<T>.Default.Compare

此内置类型支持泛型

IComparable<T>
和非泛型
IComparable
,并通过
Nullable<T>
支持引用类型、值类型和提升用法。

要了解完整的 operator 用法,请查看 MiscUtil 的

Operator
GreaterThan
等,如果您真的想要使用运算符(而不是接口),这可能会很有用。它还提供对其他运算符的访问,例如
Add
等。


5
投票

Stackoverflow 上充斥着此类问题。 看看这个搜索。 C# 不支持定义受数字约束的泛型类型的方法。遗憾的是,最好的选择是在所有对象上实现扩展方法,并根据类型进行切换,或者为整数、双精度、浮点数等创建一组方法。


0
投票

此解决方法可能会有所帮助:使用策略的解决方法。它提供编译时安全性。

© www.soinside.com 2019 - 2024. All rights reserved.