Ahmed
Ahmed

Reputation: 15039

should calling indexof call Equals?

I have a List < MyObj >

I have also overriden Equals(Object) in class MyObj.

When I call indexof on my list it does not get any index and equals is not called.

Is my assumption correct that Equals(Object) should be called when I call index of ?

If not how do I find MyObj objects if I do not have exact reference but objects are logically same,,,?

here is the code I am using

 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);
        }


    }

this is how I am call the collection

  int artistIndex = serverDirs.Children.IndexOf(new TreeNode<String>(artist));

in the index returned in always -1 even though the item is there in the children Thanks,

Upvotes: 3

Views: 2738

Answers (2)

Hans Passant
Hans Passant

Reputation: 941605

Look in the Error List window after you rebuild your program:

warning CS0114: 'ConsoleApplication1.TreeNode.Equals(object)' hides inherited member 'object.Equals(object)'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword. c:\Windows\Microsoft.NET\Framework\v2.0.50727\mscorlib.dll: (Related file)

What this is telling you is that your Equals() method does not in fact override the Equals() method that the equality comparer is going to use. Which is why you don't see it being called and why you get a -1 return from IndexOf(). Fix:

    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);
    }

This fixes your problem, albeit that you now get a new warning:

warning CS0659: 'ConsoleApplication1.TreeNode' overrides Object.Equals(object o) but does not override Object.GetHashCode()

Don't ignore that, it's going to byte sooner or later. Fix:

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

The lesson to learn from this: don't ignore warnings. The compiler is often correct when it flags something smelly. And feel free to blame the IDE, it doesn't show the Error List window when there are only warnings. Sloppy.

Upvotes: 1

DocMax
DocMax

Reputation: 12164

The Remarks for List<T>.IndexOf on MSDN include:

This method determines equality using the default equality comparer EqualityComparer.Default for T, the type of values in the list.

And if you follow that link, you will find that yes, unless you implement IEquatable<T> for your class, the default comparer will use both your GetHashCode and your Equals methods for MyObj. (You are implementing both, right?

Upvotes: 4

Related Questions