使用哪个?在这种情况下IComparable通用或非通用

问题描述

| 我有一个通用的BST和一个dataItem类来充当treeNode的值。
public class BinarySearchTree<T> : ICollection<T>  where T : IComparable
{

}

public class EnglishDictionaryWord
    : IComparer<EnglishDictionaryWord>,IComparable<EnglishDictionaryWord>
{
    public EnglishDictionaryWord(string word,WordCompareType type)
    {
        Word = word;
        Length = Word.Length;
        _compareType = type;
    }

    public int Compare(EnglishDictionaryWord x,EnglishDictionaryWord y)
    {
        if (_compareType == WordCompareType.Length)
            return new WordLengthComparer().Compare(x,y);
        else if (_compareType == WordCompareType.Lexical)
            return new WordLexicalComparer().Compare(x,y);
        else
            throw new InvalidOperationException(\"Unsupported Comparison type\");
    }

    public int Compareto(EnglishDictionaryWord obj)
    {
        return Compare(this,obj);
    }
} 

public class WordLengthComparer : IComparer<EnglishDictionaryWord>
{
    public WordLengthComparer()
    {

    }
    public int Compare(EnglishDictionaryWord x,EnglishDictionaryWord y)
    {
        return x.Length - y.Length;
    }
}

and similar Lexical comparer class.
现在,当我尝试使用时:
BinarySearchTree<EnglishDictionaryWord> _tree = 
    new BinarySearchTree<EnglishDictionaryWord>();
我得到编译错误: \'DsLib.EnglishDictionaryWord \'类型不能用作通用类型或方法'DsLib.BinarySearchTree \'中的类型参数\'T \'。没有从\'DsLib.EnglishDictionaryWord \'到\'System.IComparable \'的隐式引用转换。 如果我尝试使
public class BinarySearchTree<T> : ICollection<T>  where T : IComparable<T>
然后我得到关于装箱转换不可用的编译错误。 类型\'T \'不能用作通用类型或方法'DsLib.BinaryTreeNode \'中的类型参数\'T \'。没有从\'T \'到\'System.IComparable \'的装箱转换或类型参数转换。 我有两个问题: (1)。 我对泛型实现感到困惑。能否详细说明一个问题?和一般模式,以避免将来出现此类错误。 何时使用
IComparable<T>
,何时使用
IComparable
。 (2)。在dataitem类中包含比较器之后,这种比较器模式是否正确?因为用户会提供新的
EnglishWord
插入树中。他可能会对每个单词使用不同的比较器。然后它将打破树。 编辑:添加了BSTNode类代码
public class BinaryTreeNode<T> where T : IComparable
{
    public BinaryTreeNode(T value)
    {
        Value = value;
    }

    public T Value { get; protected internal set; }
    public BinaryTreeNode<T> Right { get; protected internal set; }
    public BinaryTreeNode<T> Left { get; protected internal set; }
    public BinaryTreeNode<T> Parent { get; protected internal set; }

    public int Height { get; protected internal set; }
}
    

解决方法

        我尝试使用以下定义的代码:
  public class BinarySearchTree<T>
      : ICollection<T>
      where T : IComparable<T>

  public class EnglishDictionaryWord
      : IComparer<EnglishDictionaryWord>,IComparable<EnglishDictionaryWord>

  public class WordLengthComparer
      : IComparer<EnglishDictionaryWord>
而且效果很好-可以编译,执行等...(。NET 4.0,C#):
 BinarySearchTree<EnglishDictionaryWord> _tree = 
     new BinarySearchTree<EnglishDictionaryWord>();
并回答您的其他问题: 您应该始终偏爱
IComparable<T>
而不是
IComparable
。它更快,更不容易出错(无投射/装箱/拆箱)等...至于您的问题:为什么要这样做?这很简单-
IComparable<T>
IComparable
是不同的类型(它们具有相似的名称,但不要让它感到困惑-类型是不同的)。因此,您只需要在引用的任何地方放置相同的类型。 插入树中的数据应具有比较逻辑。定义树时,您确切指定了它将使用的项目类型-因此,只要该对象存在,就不能在其中添加一些完全不同的类型。例如,如果您定义:
BinarySearchTree<EnglishDictionaryWord> _tree;
您无法在
_tree
中添加其他内容,例如
SpanglishDictionaryWord
,因此树确实保留了其结构,因为仅添加了
EnglishDictionaryWord
的项目,并且它们定义了结构并且比较了一致的逻辑。 编辑我只是看到您有一个“具有”比较器逻辑,而不是纯的“具有”可比性。这应该是固定的(从数据项中删除对比较器的引用)-如果不正确,那么您是正确的-树可能会损坏... EDIT2如果您需要数据项具有灵活的比较逻辑(即更改它们的比较方式,这很奇怪,请考虑一下),则BST必须引用您打算与之使用的比较器实例它:要么将包裹比较器和实际项目的项目放在一起,要么将项目的比较器作为BST的一个属性,并在确定要转到哪个分支时在每个数据项目上使用该项目。     ,        您还需要更改
BinaryTreeNode
public class BinaryTreeNode<T> where T : IComparable<T>
    ,           如果在与树相关的类/方法中的任何地方更改为
IComparable<T>
,它将进行编译。为什么要这样做?
IComparable<T>
不会继承
IComparable
。   还有第二个问题? 您是对的-如果不同的项目具有不同的排序类型,则列表将出现故障。更好的模式是让类型拥有一个默认的默认排序行为,然后允许该集合接受并使用备用IComparers。若要查看实际效果,请检查Enumerable.OrderBy的重载     

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...