为什么不';t列表.包含我所期望的工作

本文关键字:期望 工作 包含我 列表 为什么不 | 更新日期: 2023-09-27 18:27:08

为什么这个程序打印"未添加",而我认为它应该打印"添加"?

using System;
using System.Collections.Generic;
class Element
{
    public int id;
    public Element(int id)
    {
        this.id = id;
    }
    public static implicit operator Element(int d)  
    {
        Element ret = new Element(d);
        return ret;
    }
    public static bool operator ==(Element e1, Element e2)
    {
        return (e1.id == e2.id);
    }
    public static bool operator !=(Element e1, Element e2)
    {
        return !(e1.id == e2.id);
    }
}
class MainClass
{
    public static void Main(string[] args)
    {
        List<Element> element = new List<Element>();
        element.Add(2);
        if(element.Contains(2))
            Console.WriteLine("added");
        else
            Console.WriteLine("not added");
    }
}

Contains方法不使用==运算符‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌.问题出在哪里?

为什么不';t列表.包含我所期望的工作

Contains方法不使用==运算符‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌

否-它使用Equals,您尚未覆盖它。。。因此,您得到了Equals的默认行为,即检查引用标识。您应该重写Equals(object)GetHashCode以使它们彼此一致——为了理智起见,也要与您的==重载保持一致。

我还建议实现IEquatable<Element>List<Element>将优先使用Equals(object),因为EqualityComparer<T>.Default会适当地选择它。

哦,您的运算符重载也应该处理空引用。

我还强烈建议使用私有字段而不是公共字段,并使您的类型不可变-密封它并使id只读。为可变类型实现相等可能会导致奇怪的情况。例如:

Dictionary<Element, string> dictionary = new Dictionary<Element, string>();
Element x = new Element(10);
dictionary[x] = "foo";
x.id = 100;
Console.WriteLine(dictionary[x]); // No such element!

之所以会发生这种情况,是因为哈希代码会发生变化(至少在大多数实现中是这样),因此字典下面的哈希表甚至无法找到对已经存在的相同对象的引用。

所以你的课看起来像这样:

internal sealed class Element : IEquatable<Element>
{
    private readonly int id;
    public int Id { get { return id; } }
    public Element(int id)
    {
        this.id = id;
    }
    public static implicit operator Element(int d)  
    {
        return new Element(d);
    }
    public static bool operator ==(Element e1, Element e2)
    {
        if (object.ReferenceEquals(e1, e2))
        {
            return true; 
        }
        if (object.ReferenceEquals(e1, null) ||
            object.ReferenceEquals(e2, null))
        {
            return false; 
        }
        return e1.id == e2.id;
    }
    public static bool operator !=(Element e1, Element e2)
    {
        // Delegate...
        return !(e1 == e2);
    }
    public bool Equals(Element other)
    {
        return this == other;
    }
    public override int GetHashCode()
    {
        return id;
    }
    public override bool Equals(object obj)
    {
        // Delegate...
        return Equals(obj as Element);
    }
}

(顺便说一句,我不确定隐式转换的优点——我自己通常会远离这些。)

Contains方法不使用==运算符‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌.问题出在哪里?

这是正确的。

此方法[Contains]通过使用默认的相等比较器来确定相等,该比较器由T(列表中值的类型)的IEquatable.Equals方法的对象实现定义。

http://msdn.microsoft.com/en-us/library/bhkz42b3(v=vs.110).aspx

您还需要重写Equals()。请注意,当您重载Equals()时,也重写GetHashCode()几乎总是正确的。

覆盖EqualsGetHashCode,如:

class Element
{
    public int id;
    protected bool Equals(Element other)
    {
        return id == other.id;
    }
    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;
        if (obj.GetType() != this.GetType()) return false;
        return Equals((Element) obj);
    }
    public override int GetHashCode()
    {
        return id; //or id.GetHashCode();
    }
 //..... rest of the class

参见:List<T>.Contains Method

此方法通过使用默认相等来确定相等比较器,由对象的T(列表中值的类型)的IEquatable<T>.Equals方法。