调用 IndexOf 方法时应该同时调用 Equals 方法吗?

3

我有一个List<MyObj>

我在类MyObj中重写了Equals(Object)方法。

当我在我的列表上调用indexof时,它没有得到任何索引,并且equals方法也没有被调用。

我的假设是正确的吗?当我调用indexof时,Equals(Object)应该被调用吗?

如果不是,那么如果我没有准确引用对象但对象在逻辑上相同,我该如何找到MyObj对象?

这是我正在使用的代码

 public class TreeNode<T>
    {
        private readonly List<TreeNode<T>> _children = new List<TreeNode<T>>();     

        public TreeNode(T value)
        {
            Value = value;
        }

        public virtual bool Equals(Object obj)
        {
            TreeNode<T> treeNode = (TreeNode<T>)obj;

            if (treeNode.Value.Equals(Value))
                return true;
            else
                return false;
        }


        public TreeNode<T> this[int i]
        {
            get { return _children[i]; }
        }

        public TreeNode<T> Parent { get; private set; }
        public T Value { get; set; }

        public ReadOnlyCollection<TreeNode<T>> Children
        {
            get { return _children.AsReadOnly(); }
        }

        public TreeNode<T> AddChild(T value)
        {
            var node = new TreeNode<T>(value) { Parent = this };
            _children.Add(node);
            return node;
        }

        public bool RemoveChild(TreeNode<T> node)
        {
            return _children.Remove(node);
        }

        public void Traverse(Action<T> action)
        {
            action(Value);
            foreach (var child in _children)
                child.Traverse(action);
        }


    }

这是我称之为集合的方式。
  int artistIndex = serverDirs.Children.IndexOf(new TreeNode<String>(artist));

返回的索引始终为-1,即使该项存在于子节点中。

谢谢。
2个回答

4

List<T>.IndexOf的备注在MSDN中包括:

此方法使用列表中值的类型 T 的默认相等比较器 EqualityComparer.Default 来确定相等性。

如果你遵循该链接,你会发现,除非你为你的类实现了IEquatable<T>,否则默认比较器将使用你的GetHashCodeEquals方法来比较MyObj。(你确实都实现了吧?)


公平地说,对于 List<T>,您不需要 GetHashCode,但是如果您将 MyObj 放入 Dictionary 中,则需要。最好在实现任何一个时都实现两个。对于您的 IndexOf 调用,Equals 应该可以工作,除非您的比较本身存在问题。如果需要更多输入,代码会有所帮助。 - DocMax
你可以让gethashcode()抛出一个异常,这样你就能知道它何时被使用了。 - user180326

1

在重新构建程序后,请查看错误列表窗口:

警告 CS0114:“ConsoleApplication1.TreeNode.Equals(object)”隐藏了继承的成员“object.Equals(object)”。要使当前成员覆盖该实现,请添加override关键字。否则,添加new关键字。 c:\Windows\Microsoft.NET\Framework\v2.0.50727\mscorlib.dll:(相关文件)

这告诉您的是,您的Equals()方法实际上并没有覆盖相等比较器将要使用的Equals()方法。这就是为什么您没有看到它被调用,以及为什么IndexOf()返回-1的原因。修复方法:

    public override bool Equals(Object obj) {        // NOTE: override, not virtual
        TreeNode<T> treeNode = obj as TreeNode<T>;
        if (treeNode == null) return false;
        return treeNode.Value.Equals(Value);
    }

这将解决您的问题,但现在会出现一个新的警告:

warning CS0659:'ConsoleApplication1.TreeNode' 覆盖了 Object.Equals(object o) 但未覆盖 Object.GetHashCode()

不要忽略它,迟早会对您造成麻烦。修复方法:

    public override int GetHashCode() {
        return Value.GetHashCode();
    }

从中可以得到的教训是:不要忽略警告。编译器在标记出可疑代码时通常是正确的。如果只有警告而没有错误列表窗口,那么可以毫不客气地责怪IDE。这种做法很草率。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接