当将EqualityComparer作为最后一个参数传递给Linq Join方法时,它没有使用它的Equals方法,它出于某种原因使用GetHashCode来比较项目。
是否可以改为使用Equals?
var ss = new string[] { "aa", "bb", "cc" };
var zz = new string[] { "aa", "zz", "cc" };
var res = ss
.Join(zz,
o => o,
i => i,
(i, o) => i + o,
new GenericEqualityComparer<String>((x,y) => x == y))
.ToList();
答案 0 :(得分:1)
当IEqualityComparer<T>
与对象进行比较时,它首先比较它们的哈希码。只有它们相等时,才使用Equals
方法来优化比较。因此,在您的情况下,它至少应该Equals
两次。
为了演示EqualityComparer的作用,我在Linqpad中创建了一个小代码片段:
void Main()
{
var ss = new string[] { "aa1", "bb1", "cc1" };
var zz = new string[] { "aa2", "aa3", "zz2", "cc2" };
var res = ss.Join(zz, o => o, i => i, (i, o) => i + o,
new SubstringComparer()).ToList();
}
public class SubstringComparer : IEqualityComparer<string>
{
public bool Equals(string left, string right)
{
string.Format("{0} - {1}", left, right).Dump();
return left.Substring(0,2) == right.Substring(0,2);
}
public int GetHashCode(string value)
{
value.Dump();
return value.Substring(0,2).GetHashCode();
}
}
如果前两个字符相等,则字符串相等。输出是:
AA2
AA3
aa2 - aa3
zz2所示
CC2
AA1
aa2 - aa1
BB1
CC1
cc2 - cc1
结果列表:
aa1aa2
aa1aa3
cc1cc2
你看到第一个第二个列表被比较(我不知道为什么,顺便说一下,可能是缓存的哈希码),然后是对。
因此,当您的GenericEqualityComparer
永远不会点击Equals
时,它总会生成一个唯一的哈希码,我认为这应该是一个错误。如果并非总是使用Equals
,则说明如下。如果你想比较器总是使用Equals
,你应该让它总是返回一个相同的哈希码(当然效率很低)。
答案 1 :(得分:0)
https://stackoverflow.com/a/3719802/136967
有一个非常好的解释。基本上,使用Equals()进行比较,但Linq代码在进行处理时使用GetHashCode(),如果没有正确实现,则会给出奇怪的答案。
hth,
艾伦。