如果属性正确匹配,我试图通过连接两个列表来创建列表。我使用以下命令:
FooList = TrackedStrings.Join (FooList,
str => str,
Foo => Foo.GetString (),
(str, Foo) => Foo,
new Comparer ())
.ToList ();
以下要比较的课程:
public class Comparer : IEqualityComparer<string>
{
public bool Equals (string x, string y)
{
return y.Contains (x);
}
public int GetHashCode (string str)
{
return str.GetHashCode ();
}
}
现在,我的想法是我只想保留包含来自TrackedStrings的任何一个字符串的GetString()的项目。但是,它不起作用:如果字符串相等,则comparer仅返回true。例如,假设我们有两个列表:
List<string> TrackedActions = new List<string> { "Created", "Deleted" };
List<Foo> FooList = new List<FooList> { new Foo ("Created"), new Foo ("Deleted Something")};
使用当前命令,第二个Foo从列表中删除 - 而不是匹配到TrackedActions[1]
并保留。
因此,我的问题是:为什么Comparer
没有像我期望的那样工作?
答案 0 :(得分:2)
自定义比较器必须确保其定义的Equals
关系为symmetric。这意味着只要x.Equals(y)
,y.Equals(x)
,反之亦然。
这样做的原因是你永远无法预测元素的比较顺序,即调用哪一个:
aStringFromLeftList.Equals(aStringFromRightList)
或
aStringFromRightList.Equals(aStringFromLeftList)
因为您需要的关系既不对称也不传递,您不能使用Comparer来解决问题。
答案 1 :(得分:2)
您不应该使用IEqualityComparer,因为The Equals method is reflexive, symmetric, and transitive.
MSDN
在您的情况下,它不对称Equals(a,b) != Equals (b,a)
格洛芬德的回答也不完全正确,因为它不是传递性的:
Equals("abcd","bc") == true
Equals("bcde", "bc") == true
Equals("abcd","bcde") == false
答案 2 :(得分:1)
您的比较器不起作用是由于GetHashCode()
的实施
无论采用正确方式实施IEqualityComparer
。
匹配由
完成Deleted Something
肯定会返回与Deleted