【问题标题】:Generic constraint to match numeric types [duplicate]匹配数字类型的通用约束[重复]
【发布时间】:2011-03-20 18:20:45
【问题描述】:

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

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

只是where T : struct 不行,因为它也会匹配stringbool,可能还有我忘记的其他内容。我能做些什么来只匹配数字类型吗? (特别是实现 &gt;&lt; 运算符的类型,所以我可以比较它们......如果这意味着我也在匹配日期,那并不重要 - 扩展仍然会按照我的预期进行。 )

【问题讨论】:

标签: c# generics numeric


【解决方案1】:

在这种情况下,您希望将泛型限制为IComparable 接口,这使您可以访问CompareTo 方法,因为该接口允许您回答问题ShouldBeGreaterThan

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

【讨论】:

  • 这是一个比数字类型更通用的操作界面更好的解决方案,至少对于这个问题。
  • 有没有办法允许使用==&gt; 等而不是.Equals().CompareTo
  • 那些操作符是作为静态方法实现的——也就是说,目前C#没有办法限制一个类型的静态特征,
  • 请注意,IComparable 似乎只在比较相同类型的对象时才有效。例如,调用 123.CompareTo(123L) 似乎不起作用,这可能是一个问题,具体取决于您要实现的目标。
【解决方案2】:
where T : struct, 
          IComparable, 
          IComparable<T>, 
          IConvertible, 
          IEquatable<T>, 
          IFormattable

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

还有一些其他的东西可以实现这些 - 例如 DateTime,所以它并不是真正需要的,但可以防止很多你不想要的实例化。

【讨论】:

  • 即便如此,我似乎也无法使用常见的数学运算。 Operator '==' cannot be applied to operands of type 'T' and 'float'
【解决方案3】:
public static bool IsGreaterThan<T>(this T actual, T comp) where T : IComparable<T>
{
    return actual.CompareTo(comp) > 0;
}

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

【讨论】:

    【解决方案4】:

    很难仅限于数字,因为没有像 INumeric 这样的常用过滤器。实际上,我怀疑这里最简单的方法是坚持约束,并在方法中使用Comparer&lt;T&gt;.Default.Compare

    这种内置类型支持泛型IComparable&lt;T&gt; 和非泛型IComparable,并通过Nullable&lt;T&gt; 支持引用类型、值类型和提升使用。

    对于完整的 operator 用法,请查看 MiscUtil's Operator classGreaterThan 等,如果您真的想要使用 operator(而不是界面),这可能会很有用)。它还提供对其他运算符的访问,例如 Add 等。

    【讨论】:

    • Marc Gravell 说“很难限制为数字”,但在运行时和编译时都是可能。请参阅我对“是否存在将我的泛型方法限制为数字类型的约束?”的回答。问题。stackoverflow.com/questions/32664/…
    • @Erez 这会起作用,但对性能至关重要的代码来说是死亡 - 大量的装箱和类型检查。在 C#7.2-C#8.0 时期的某个地方,我们可能会看到对泛型的添加以更有效地做到这一点。
    • 我已经等不及微软支持了。
    【解决方案5】:

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

    【讨论】:

      【解决方案6】:

      此解决方法可能会有所帮助:Workaround using policies。它提供编译时安全性。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-04-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-10-06
        相关资源
        最近更新 更多