等于不在自定义类上工作

时间:2016-09-20 19:18:49

标签: c# list override equals

我知道这个问题已被问过几次C#,我已经经历了几个不同的例子,并开始放松我的想法。

我有一个自定义类用于列表,我试图比较它的两个实例以确定它们是否相等,并最终查看是否存在重复(但首先是第一件事)。

它只是一个包含几个字符串项的简单类型类。当我尝试使用“==”或.Equals()比较两个列表时,它总是返回false。 我见过的例子使用了似乎来自同一个类的Equals覆盖。这是它自己的类,我试图在不同的类中比较它们。为了简单起见,我创建了一个测试项目来处理Equals问题。我一直在检查一个字段,看看我是否可以得到它工作,没有运气。

奇怪的是,即使在equals方法或gethashcode方法中的任何位置设置断点也是如此。 VS 2015中的调试器不会停止代码,就像根本没有调用方法一样。

如果有人可以帮我解决我的错误,那就太棒了!

    class TagContainer : IEquatable<TagContainer>
      {
    public int idNo { get; set; }
    public string filePath { get; set; }
    public string artists { get; set; }
    public string album { get; set; }
    public string genre { get; set; }
    public string title { get; set; }
    public string year { get; set; }

    public TagContainer()

    {
        idNo = idNo;
        filePath = filePath;
        artists = artists;
        album = album;
        genre = genre;
        title = title;
        year = year;
    }



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

        return this.filePath.Equals(filePath);
    }

    public override bool Equals(Object obj)
    {
        if (ReferenceEquals(null, obj)) return false;

        if (ReferenceEquals(this, obj)) return true;

        if (obj.GetType() != GetType()) return false;

        TagContainer tc = (TagContainer)obj;
        return filePath == tc.filePath;


    }

    public override int GetHashCode()
    {

        unchecked
        {
            var hashCode = 13;
            var myStrHashCode = !string.IsNullOrEmpty(filePath) ?
                 filePath.GetHashCode() : 0;
            return hashCode * myStrHashCode;
        }
    }
}

我也有测试,创建列表,然后检查它们是否相等。

public partial class Form1 : Form
{
    List<TagContainer> tc1 = new List<TagContainer>();
    List<TagContainer> tc2 = new List<TagContainer>();

    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        addtoTC1();
        addtoTC2();

        textBox1.Text = tc1.Equals(tc2).ToString();

    }

    public void addtoTC1()
    {
        TagContainer tc = new TagContainer()
        {
            idNo = 1,
            filePath = "file1",
            artists = "artist 1",
            album = "album1",
            genre = "genre1",
            title = "title1",
            year = "2016"
        };
        tc1.Add(tc);

        TagContainer tg = new TagContainer()
        {
            idNo = 1,
            filePath = "file2",
            artists = "artist 2",
            album = "album2",
            genre = "genre2",
            title = "title2",
            year = "2016"
        };

        tc1.Add(tg);

    }

    public void addtoTC2()
    {
        TagContainer tc = new TagContainer()
        {
            idNo = 1,
            filePath = "file1",
            artists = "artist 1",
            album = "album1",
            genre = "genre1",
            title = "title1",
            year = "2016"
        };
        tc2.Add(tc);

        TagContainer tg = new TagContainer()
        {
            idNo = 1,
            filePath = "file2",
            artists = "artist 2",
            album = "album2",
            genre = "genre2",
            title = "title2",
            year = "2016"
        };

        tc2.Add(tg);

    }



}

2 个答案:

答案 0 :(得分:6)

这会返回false,因为tc1tc2List<TagContainer>的两个不同实例。

tc1.Equals(tc2)

你永远不会超越List<TagContainer>.Equals()。你覆盖了TagContainer.Equals()List<TagContainer>TagContainer是两个完全不同的类,List<T>.Equals()无法比较两个列表的内容。它只是检查它们是否都是同一个对象实例。对于任何引用类型,这是Equals()的默认行为。

试试这个

var eq = tc1.SequenceEqual(tc2);

这将比较列表的内容,如果两个列表具有相同的内容,则返回true。它将为两个列表中的每对项目调用TagContainer.Equals():项目零对项目零,项目一对项目一等,等等。

如果你真的只想比较路径,那就更好了:

var tc1Paths = tc1.Select(tc => tc.filePath.ToLower()).OrderBy(s => s);
var tc2Paths = tc2.Select(tc => tc.filePath.ToLower()).OrderBy(s => s);

var eq = tc1Paths.SequenceEqual(tc2Paths);

...并且根本不会覆盖Equals()。覆盖Equals()会产生奇怪的效果,如果您真正想要做的只是比较路径列表,则不需要它。

答案 1 :(得分:1)

正如另一个答案所述,您没有检查序列相似性。但是你的equals方法也存在缺陷。您正在比较第一个equals方法中的同一个对象:

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

    return this.filePath.Equals(obj.filePath); // <-- here you were comparing to this
}