获取List.Join进行正确比较

时间:2015-07-22 08:33:59

标签: c# list compare

如果属性正确匹配,我试图通过连接两个列表来创建列表。我使用以下命令:

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没有像我期望的那样工作?

3 个答案:

答案 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

匹配由

完成
  1. 比较2个字符串的哈希码。在您的情况下,Deleted Something肯定会返回与Deleted
  2. 不同的哈希码
  3. 如果(1)相等,则再次使用Equals()进行比较,因为HashCode可能有碰撞但不准确,但速度很快。