我知道这个问题已被问过几次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);
}
}
答案 0 :(得分:6)
这会返回false,因为tc1
和tc2
是List<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
}