将通用参数转换为 IComparable

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

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>>' 的隐式引用转换。

以下是代码:

void CheckComparable&lt;C&gt;(C a, C b) 
    where C : IComparable&lt;C&gt;
{
   a.CompareTo(b).Should().BePositive();
   b.CompareTo(a).Should().BeNegative();
}

void CheckConformance&lt;T&gt;(T a, T b)
{
    if (a is IComparable&lt;T&gt; aComp &amp;&amp; b is IComparable&lt;T&gt; bComp)
    {
        this.CheckComparable(aComp, bComp);
    }
}
英文:

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:

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

This is the code:

void CheckComparable&lt;C&gt;(C a, C b) 
    where C : IComparable&lt;C&gt;
{
   a.CompareTo(b).Should().BePositive();
   b.CompareTo(a).Should().BeNegative();
}

void CheckConformance&lt;T&gt;(T a, T b)
{
    if (a is IComparable&lt;T&gt; aComp &amp;&amp; b is IComparable&lt;T&gt; bComp)
    {
        this.CheckComparable(aComp, bComp);
    }
}

答案1

得分: 1

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

// 我们希望a与b可比较
void CheckComparable<C>(IComparable<C> a, C b) {
  a.CompareTo(b); // 在这里调用它
}

void CheckConformance<T>(T a, T b) {
  if (a is IComparable<T> aComp) {
    CheckComparable<T>(aComp, b);
  }
}

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

void CheckComparable<C>(C a, C b, IComparer<C> comparer = default) {
  // 如果没有提供显式的比较器,我们将获得默认的比较器:
  // 如果C实现了IComparable<C>,它将基于.CompareTo
  comparer ??= Comparer<C>.Default;

  // 默认情况下,C不能与自身进行比较,且没有提供比较器
  // 所以,我们将此测试从CheckConformance移到这里
  if (comparer is null)
    return;

  // 在这里稍微修改了语法:使用comparer而不是CompareTo
  comparer.Compare(a, b); // 在这里调用它
}

void CheckConformance<T>(T a, T b) {
  // 这里不需要检查
  CheckComparable(a, b);
}
英文:

Technically, we can put something like this:

// We want a be comparable with with b
void CheckComparable&lt;C&gt;(IComparable&lt;C&gt; a, C b) {
  a.CompareTo(b); // call this here
}

void CheckConformance&lt;T&gt;(T a, T b) {
  if (a is IComparable&lt;T&gt; aComp) {
    CheckComparable&lt;T&gt;(aComp, b);
  }
}

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

void CheckComparable&lt;C&gt;(C a, C b, IComparer&lt;C&gt; comparer = default) {
  // If no explicit comparer is provided, we get default one:
  // It will be .CompareTo based in case C implements IComparable&lt;C&gt; 
  comparer ??= Comparer&lt;C&gt;.Default;

  // C can&#39;t be compared with itself by default and no comparer provided
  // So, we move test here from CheckConformance
  if (comparer is null)
    return;

  // Slightly modified syntax here: comparer instead of CompareTo
  comparer.Compare(a, b); // call this here
}

void CheckConformance&lt;T&gt;(T a, T b) {
  // No check required here
  CheckComparable(a, b);
}

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:

确定