将通用参数转换为 IComparable

huangapple go评论98阅读模式
英文:

Cast generic parameter to IComparable<T>

问题

我有一个通用函数,用于检查给定的参数是否是 IComparable<T>,如果是的话则调用适当的方法。但我无法编译代码。

我收到以下消息:

[CS0311] 类型 'System.IComparable<T>' 不能用作泛型类型或方法 'ValueObjectConformanceTestHelper.CheckComparable<T>(T, T, T)' 中的类型参数 'T'。
没有从 'System.IComparable<T>' 到 'System.IComparable<System.IComparable<T>>' 的隐式引用转换。

以下是代码:

  1. void CheckComparable&lt;C&gt;(C a, C b)
  2. where C : IComparable&lt;C&gt;
  3. {
  4. a.CompareTo(b).Should().BePositive();
  5. b.CompareTo(a).Should().BeNegative();
  6. }
  7. void CheckConformance&lt;T&gt;(T a, T b)
  8. {
  9. if (a is IComparable&lt;T&gt; aComp &amp;&amp; b is IComparable&lt;T&gt; bComp)
  10. {
  11. this.CheckComparable(aComp, bComp);
  12. }
  13. }
英文:

I have a generic function that checks if given arguments are IComparable<T> and if they are call an appropriate method. But I do not get the code compiled.

I get this message:

  1. [CS0311] The type &#39;System.IComparable&lt;T&gt;&#39; cannot be used as type parameter &#39;T&#39;
  2. in the generic type or method &#39;ValueObjectConformanceTestHelper.CheckComparable&lt;T&gt;(T, T, T)&#39;.
  3. There is no implicit reference conversion from &#39;System.IComparable&lt;T&gt;&#39;
  4. to &#39;System.IComparable&lt;System.IComparable&lt;T&gt;&gt;&#39;.

This is the code:

  1. void CheckComparable&lt;C&gt;(C a, C b)
  2. where C : IComparable&lt;C&gt;
  3. {
  4. a.CompareTo(b).Should().BePositive();
  5. b.CompareTo(a).Should().BeNegative();
  6. }
  7. void CheckConformance&lt;T&gt;(T a, T b)
  8. {
  9. if (a is IComparable&lt;T&gt; aComp &amp;&amp; b is IComparable&lt;T&gt; bComp)
  10. {
  11. this.CheckComparable(aComp, bComp);
  12. }
  13. }

答案1

得分: 1

技术上,我们可以像这样做:

  1. // 我们希望a与b可比较
  2. void CheckComparable<C>(IComparable<C> a, C b) {
  3. a.CompareTo(b); // 在这里调用它
  4. }
  5. void CheckConformance<T>(T a, T b) {
  6. if (a is IComparable<T> aComp) {
  7. CheckComparable<T>(aComp, b);
  8. }
  9. }

然而,这看起来很奇怪和难读。为什么不传递 IComparer<C> 呢?

  1. void CheckComparable<C>(C a, C b, IComparer<C> comparer = default) {
  2. // 如果没有提供显式的比较器,我们将获得默认的比较器:
  3. // 如果C实现了IComparable<C>,它将基于.CompareTo
  4. comparer ??= Comparer<C>.Default;
  5. // 默认情况下,C不能与自身进行比较,且没有提供比较器
  6. // 所以,我们将此测试从CheckConformance移到这里
  7. if (comparer is null)
  8. return;
  9. // 在这里稍微修改了语法:使用comparer而不是CompareTo
  10. comparer.Compare(a, b); // 在这里调用它
  11. }
  12. void CheckConformance<T>(T a, T b) {
  13. // 这里不需要检查
  14. CheckComparable(a, b);
  15. }
英文:

Technically, we can put something like this:

  1. // We want a be comparable with with b
  2. void CheckComparable&lt;C&gt;(IComparable&lt;C&gt; a, C b) {
  3. a.CompareTo(b); // call this here
  4. }
  5. void CheckConformance&lt;T&gt;(T a, T b) {
  6. if (a is IComparable&lt;T&gt; aComp) {
  7. CheckComparable&lt;T&gt;(aComp, b);
  8. }
  9. }

However, it looks weird and unreadable. Why not pass IComparer&lt;T&gt;?

  1. void CheckComparable&lt;C&gt;(C a, C b, IComparer&lt;C&gt; comparer = default) {
  2. // If no explicit comparer is provided, we get default one:
  3. // It will be .CompareTo based in case C implements IComparable&lt;C&gt;
  4. comparer ??= Comparer&lt;C&gt;.Default;
  5. // C can&#39;t be compared with itself by default and no comparer provided
  6. // So, we move test here from CheckConformance
  7. if (comparer is null)
  8. return;
  9. // Slightly modified syntax here: comparer instead of CompareTo
  10. comparer.Compare(a, b); // call this here
  11. }
  12. void CheckConformance&lt;T&gt;(T a, T b) {
  13. // No check required here
  14. CheckComparable(a, b);
  15. }

huangapple
  • 本文由 发表于 2023年7月12日 20:58:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/76670844.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定