.net - 使用哪个? IComparable 泛型或非泛型在这种情况下

标签 .net generics collections

我有一个通用的 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).这个比较器模式是否正确,在数据项类中有比较器?因为用户会提供新的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 的项目添加,并且它们定义了一致的结构和比较逻辑。
    编辑 我刚刚看到你有一个“有”比较器逻辑,而不是纯粹的"is"比较。这应该是固定的(从数据项中删除对比较器的引用) - 如果没有,你是对的 - 树可能会被破坏......
    编辑2 如果您需要数据项具有灵活的比较逻辑(即更改它们的比较方式,这很奇怪,请考虑一下),那么 BST 必须引用您打算与之一起使用的比较器的实例: 要么把包装比较器的项目和实际项目放在一起,或者把项目的比较器作为 BST 的一个属性,并在决定去哪个分支时在每个数据项上使用它。

    关于.net - 使用哪个? IComparable 泛型或非泛型在这种情况下,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6176304/

    相关文章:

    c# - 如何测试一个空的 generic.dictionary 集合?

    java - 为任何可比较集合编写排序方法 (Java)

    .net - 如何在 Windows Workflow 中的事件之间传递数据?

    c# - 属性信息 : is the property an indexer?

    java - HashMap<类<?>, 列表<类<?>>> : specify that the lists' classes extend the keys'

    node.js - 在 NodeJS 上的 Firestore 中获取集合中的所有数据

    java - 按值对 Map<Key, Value> 进行排序

    .net - 在 IE8 中嵌入 .NET 用户控件

    c# - 如何使用线程异常?

    c# - 如何在不指定任何类型参数的情况下创建构造泛型类型