比较 C# 中类型为“对象”的对象

本文关键字:对象 类型 比较 | 更新日期: 2023-09-27 18:31:53

我正在尝试在C#中实现树数据结构,我已经在C++中做了100次但是在这里,当我尝试保持 Tree 泛型以接受任何数据类型时,我使每个Node的数据都包含在类型 Object 的对象中,如下所示:

    public class Node
    {
        public object Data;
        public Node Right;
        public Node Left;
        public Node(object value)
        {
            NodeContent = value;
            Right = Left = null;
        }
    }

但是当我尝试实现insert时,我需要比较两个类型 Object 的对象,以便知道是在当前节点的左侧还是右侧插入新节点。当我尝试检查此内容时

    if(value < childPtr.Data)

其中value是要插入的值,我收到一条错误消息,指出我无法比较两个类型为 Object 的对象。那么有没有办法解决这个问题呢?

比较 C# 中类型为“对象”的对象

你的方法的问题在于Data可以是任何类型的。您的设计允许您将多个类型放入同一树中。所以一个节点可能有一个string,另一个可能有一个double,第三个节点可能有一个对用户定义类型的引用。如果使 Node 构造函数采用IComparable实例,则假定树中的所有项都属于同一类型,或者它们的IComparable接口实现知道如何比较所有可能数据类型的值。

简而言之,虽然你所做的会起作用,但它根本不是安全的。

你拥有的是一个非常像C的事情要做。在C++中,您将使用模板来避免这种可憎的东西。在 C# 中,使用泛型。

我赞同评论中提出的建议:如果你想要一个通用的数据结构,那就做一个通用的数据结构。使用内置集合,例如,如果你想要一个你写的整数列表:

var list_of_integers = new List<int>();

如果你想要一个字符串列表:

var list_of_strings = new List<string>();

如果要创建通用树集合,请从以下方面开始:

public class MyGenericTree<T>
{
    public class Node
    {
        public T Data;
        public Node Left;
        public Node Right;
        public Node(T data)
        {
            Data = data;
        }
    }
    private readonly IComparer<T> _comparer;
    public MyGenericTree(IComparer<T> comparer = null)
    {
        _comparer = comparer ?? Comparer<T>.Default;
    }
}

然后你用它创建它:

var myTree = new MyGenericTree<string>(); // or int, or whatever type

如果你想要一个自定义比较函数,你可以写:

// Create a tree that stores case-insensitive strings
var myTree = new MyGenericTree<string>(StringComparer.CurrentCultureIgnoreCase);

这会强制Data始终为兼容类型。您可以使用该类型的默认比较器,或者使用传递给构造函数的比较器接口。

在进行比较时,它是:

int a = _comparer.Compare(node1, node2);
if (a < 0)
    // node1 < node2
else if (a > 0)
    // node1 > node2
else
    // node1 == node2

如果您确实想在树中存储非类型化的object引用,则可以轻松编写:

var myTree = new MyGenericTree<object>(some_object_comparer);

虽然你为什么要做这样的事情有点神秘。

我知道泛型开始时看起来有点奇怪,但是在使用它们一天左右之后,您就会明白它们非常灵活且类型安全。

由于您需要从数据中进行比较,因此更好的方法是:

public class Node
{
    public IComparable Data;
    public Node Right;
    public Node Left;
    public Node(IComparable value)
    {
        Data = value;
        Right = Left = null;
    }
}

稍后您可以执行以下操作:

if(value.CompareTo(childPtr.Data) < 0)