【问题标题】:Generics and IComparable - error CS00301泛型和 IComparable - 错误 CS00301
【发布时间】:2023-04-01 06:00:02
【问题描述】:

我尝试开发一个实现 IComparable 的通用类“MinHeap(T)”。当泛型为“int”或其他类“代码”时,它可以正常工作。更进一步并为 T 使用通用类“节点(代码)” 导致下面提到的错误。

我可能太新了,不了解 IComparable 和 IComparable(T) 之间的细微差别。有人有想法吗? 在此先感谢您的帮助, LJ

public class MinHeap<T> where T : IComparable
{
...
}
public class Node<T> where T : IComparable
{
    T data
...
    public int CompareTo(object obj)
    {
        Node<T> otherNode = obj as Node<T>;
        return this.data.CompareTo(otherNode.data);
    }
...
}
public class Code : IComparable
{
    public int freq;
...
    public int CompareTo(object obj)
    {
        Code otherCode = obj as Code;
        return this.freq.CompareTo(otherCode.freq);
    }
}
static void Main(string[] args)
{
    MinHeap<int> hInt = new MaxHeap<int>(heapSeed); // works fine
    MinHeap<Code> hCode = new MinHeap<Code>(codeList); // works fine
...
    Node<Code>[] nodeCodeList = new Node<Code>[freqList.Length]; // ok        
    MinHeap<Node<Code>> h = new MinHeap<Node<Code>>(nodeCodeList); // Error
...
}

错误信息:

错误 2 类型“Algorithms.Node(Algorithms.Code)”不能用作泛型类型或方法“Algorithms.MinHeap(T)”中的类型参数“T”。没有从 'Algorithms.Node(Algorithms.Code)' 到 'System.IComparable' 的隐式引用转换。

【问题讨论】:

  • T 不仅应该具有可比性,Node&lt;T&gt; 也应该具有可比性。
  • 以下应该可以工作:public class Node&lt;T&gt; : IComparable where T : IComparable。最小堆也是如此。 @Aphelion 有解释。
  • 现在工作正常 - MinHeap 不需要做同样的事情 - 非常感谢

标签: c# .net generics icomparable


【解决方案1】:

Node&lt;T&gt; 类没有实现IComparable。它只是对T 的类型有一个约束。

您似乎已尝试实现decorator 模式。也实现接口,然后将方法映射到装饰对象。

【讨论】:

  • MinHeap 不必实现 IComparable。
  • @empi 谢谢!我已经修改了答案。
  • 按照建议修改代码@leppie 感谢大家
【解决方案2】:

你最好定义你的泛型类,这样它就不需要要求类型来实现IComparable&lt;T&gt;。这就是.NET 泛型类的实现方式。他们将使用类型的默认比较,或者使用您传入的IComparer&lt;T&gt;。例如,SortedList 具有以下构造函数(以及其他构造函数):

SortedList<TKey, TValue>(); // uses default comparer for TKey
SortedList<TKey, TValue>(IComparer<T> comparer); // uses supplied comparer

很容易实现:

public class MinHeap<T>
{
    private IComparer<T> _comparer;

    public MinHeap<T>(IComparer<T> comp)
    {
        _comparer = comp;
    }

    public MinHeap<T>()
        : this(Comparer<T>.Default)
    {
    }
}

这样,您的客户可以使用MinHeap&lt;T&gt; 来保存未实现IComparable&lt;T&gt; 的类的实例。

进行比较时,请致电_comparer.Compare(item1, item2)

另一方面,您的堆没有特别需要节点。您可以在数组中实现二进制堆。例如,请参阅A Generic BinaryHeap Class

【讨论】:

    【解决方案3】:

    你应该在 Node 类中实现 IComparable 接口,像这样:

      public class Node<T>: IComparable<Node<T>> // <- IComparable<Node<T>> implemented  
        where T: IComparable  {
    
        T data;
    
        ...
    
        #region IComparable<Node<T>> Members
    
        // interface implementation, not just a method
        public int CompareTo(Node<T> other) {
          // Let us be accurate with possible nulls:  
          if (Object.ReferenceEquals(null, other))
            return 1; // <- or -1 if you think it's right
          else if (Object.ReferenceEquals(data, other.data))   
            return 0;
          else if (Object.ReferenceEquals(null, data))   
            return -1; // <- or 1 if you think it's right
    
          return data.CompareTo(other.data);
        }
    
        #endregion IComparable<Node<T>> Members
      }
    

    根据最小堆的算法,您可能还需要在 MinHeap 类中实现 IComparable>

    【讨论】:

    • 我认为您需要先执行ReferenceEquals(data, other.data)。否则,如果other.data == null,它将总是返回-1,即使this.data == null
    • 抱歉,ReferenceEquals(data, other.data) 不可能是第一个。如果 other 为空怎么办?在这种情况下 other.data 会抛出异常。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多