2

我正在使用System.Collections.Generic,其中包含我编写的类的实例。

我已经读过 collections.Contains方法使用object.Equals(),或者接口中的Equals()方法的实现。IEquatable

我已经覆盖了对象方法,以及从接口实现。但是,Queue.Contains(instance)总是返回false。我究竟做错了什么?

例如...

class Foo : IEquatable<Foo>
{
    ...
    int fooField1;
    ...

    public override bool Equals(object obj)
    {
         Foo other = obj as Foo;
         bool isEqual = false;

         if (other.fooField1 == this.fooField1)
         { 
             isEqual = true;
         }

         return isEqual;         
    }

    public bool Equals(Foo other)
    {
         bool isEqual = false;

         if (other.fooField1 == this.fooField1)
         { 
             isEqual = true;
         }

         return isEqual;         
    }

}
...

void SomeFunction()
{
    Queue<Foo> Q = new Queue<Foo>();
    Foo fooInstance1 = new Foo();
    Foo fooInstance2 = new Foo();

    fooInstance1.fooField1 = 5;
    fooInstance2.fooField1 = 5;

    Q.Enqueue(fooInstanec1);
    if(Q.Contains(fooInstance2) == false)
    {
         Q.Enqueue(fooInstance2);
    }
}

fooInstance2 总是添加到队列中。事实上,当我在调试器上运行它时,永远不会达到 Equals 的实现。

我究竟做错了什么?

4

4 回答 4

5

解决初始编译错误后,您的示例代码将按预期工作。并不是说它与提出的问题有关,请阅读覆盖 Equals (您也需要覆盖 GetHashCode 并检查 null / type-mismatch 等错误情况)。

class Foo : IEquatable<Foo>
    {
        private int _fooField1;
        public Foo(int value)
        {
            _fooField1 = value;
        }

        public override bool Equals(object obj)
        {
            return Equals(obj as Foo);
        }

        public bool Equals(Foo other)
        {
            return (other._fooField1 == this._fooField1);
        }
    }



    class Program
    {
        static void SomeFunction()
        {
            var Q = new Queue<Foo>();
            Foo fooInstance1 = new Foo(5);
            Foo fooInstance2 = new Foo(5);

            Q.Enqueue(fooInstance1);
            if (!Q.Contains(fooInstance2))
            {
                Q.Enqueue(fooInstance2);
            }
            else
            {
                Console.Out.WriteLine("Q already contains an equivalent instance ");
            }
        }

        static void Main(string[] args)
        {
            SomeFunction();
        }
    }
于 2011-01-29T03:31:12.537 回答
0

您还需要在您的类 Foo 中重写 GetHashCode() 方法。

于 2011-01-29T03:31:12.863 回答
0
fooInstance1.fooField1 = 5;
fooInstance1.fooField2 = 5;

你在那里更新fooInstance1了两次。第二行应该说fooInstance2.fooField1 = 5;

一旦修复,按预期Q.Contains返回。True


除此之外,您不一定需要实现IEquatable. 每个对象都有一个可覆盖的Equals方法。你可以简单地覆盖它。实现自己的比较方法时要小心。此示例中显示的实现对 NullReference 异常非常开放。像这样的东西会更好:

public override bool Equals(object obj)
{
    if(obj == null)
        return false;

    Foo other = obj as Foo;
    if(other == null)
        return false;

    return fooField1 == other.fooField1;
}

正如其他人所提到的,如果你走这条路线并覆盖Equals,你也应该覆盖GetHashCode。还有一些其他的事情你应该考虑。有关详细信息,请参阅此 MSDN 页面

于 2011-01-29T03:44:13.173 回答
0

为什么在 C# 中重写 Equals 方法时重写 GetHashCode 很重要?

于 2011-01-29T03:45:51.847 回答