collections.Contains(T) 方法

发布于 2024-10-15 00:28:24 字数 1255 浏览 7 评论 0原文

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

我读到集合 .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 的实现。

我做错了什么?

I am using a System.Collections.Generic, which contains instances of a class I wrote.

I have read that the collections .Contains method uses object.Equals(), or an implementation of the Equals() method from the IEquatable interface.

I have overridden the object method, as well as implemented from the interface. However, Queue.Contains(instance) is always returning false. What am I doing wrong?

For instance...

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 is always added to the queue. In fact, when I run this on the debugger, the implementations of Equals are never reached.

What am I doing wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

魔法唧唧 2024-10-22 00:28:25

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

You need GetHashCode() method overridden as well in your class Foo.

怀中猫帐中妖 2024-10-22 00:28:25
fooInstance1.fooField1 = 5;
fooInstance1.fooField2 = 5;

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

修复此问题后,Q.Contains 将按预期返回 True


Other than that, you don't necessarily need to implement IEquatable. Every object has an overridable Equals method. You can simply overwrite that. Be careful when you implement your own comparison method. Your implementation shown in this sample is very open to NullReference exceptions. Something like this would be better:

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 页面

fooInstance1.fooField1 = 5;
fooInstance1.fooField2 = 5;

You updated fooInstance1 twice there. Second line should say fooInstance2.fooField1 = 5;.

Once that's fixed, Q.Contains returns True as expected.


Other than that, you don't necessarily need to implement IEquatable. Every object has an overridable Equals method. You can simply overwrite that. Be careful when you implement your own comparison method. Your implementation shown in this sample is very open to NullReference exceptions. Something like this would be better:

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

As others have mentioned, if you go this route and override Equals, you should override GetHashCode, too. There are a few other things you should consider. See this MSDN page for details.

沉鱼一梦 2024-10-22 00:28:24

一旦初始编译错误得到解决,您的示例代码就会按预期工作。并不是说它与所提出的问题相关,请阅读有关重写 Equals 的内容(您也需要重写 GetHashCode 并检查 null / 类型不匹配等错误情况)。

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

Your sample code works as expected once the initial compile errors are sorted out. Not that it is relevant to the posed problem, Do read up on overriding Equals (you need to override GetHashCode too and check for error cases like 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();
        }
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文