List.Except不使用自定义Equals函数

时间:2014-03-18 13:05:38

标签: c#

public class eq : IEquatable<eq>
    {
        public string s1;
        public string s2;
        public override bool Equals(object obj)
        {
            if (obj == null) return false;
            eq o = obj as eq;
            if (o == null) return false;
            return Equals(o);
        }
        public bool Equals(eq o)
        {
            if (s1==o.s1 && s2==o.s2)
                return true;
            return false;
        }
        public eq (string a,string b)
        {
            s1 = a;
            s2 = b;
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            List<eq> l1 = new List<eq>();
            List<eq> l2 = new List<eq>();
            l1.Add(new eq("1", "1"));
            l1.Add(new eq("2", "2"));
            l1.Add(new eq("3", "3"));
            l2.Add(new eq("3", "3"));
            l2.Add(new eq("1", "1"));
            var b= l1.Contains(new eq("1", "1"));
            var v = l1.Except(l2);
        }
    }

l1.contains语句调用自定义函数并返回预期结果

l1.Except不会导致调用自定义函数并返回l1

的全部内容

有没有办法在不明确编写循环的情况下完成此任务?

3 个答案:

答案 0 :(得分:9)

您应该覆盖GetHashCode方法Except才能正常使用。 E.g

public override int GetHashCode()
{
    int hash = 19;
    hash = hash * 23 + (s1 == null) ? 0 : s1.GetHashCode();
    hash = hash * 23 + (s2 == null) ? 0 : s2.GetHashCode();
    return hash;
}

除了执行set操作外(在内部,它使用第二个序列中的项填充Set<T>并尝试将第一个序列中的项添加到同一个集合中。)

答案 1 :(得分:2)

实际上,Except(和Set<T>Dictionary<K, T>)首先使用哈希码,然后才会(哈希码上的冲突 >,当两个哈希码相同时) - Equals,这就是为什么每当你重新设计 Equals时你应该实现 GetHashCode as好。在你的情况下:

public class eq : IEquatable<eq> {
    public string s1;
    public string s2;

    // Your code could be shortened
    public override bool Equals(object obj) {
      return Equals(obj as eq);
    }

    public bool Equals(eq o) {
      // Do not forget, that "o" can be null
      if (Object.ReferenceEquals(null, o)) 
        return false;

      return String.Equals(s1, o.s1) && String.Equals(s2, o.s2);
    }

    public override int GetHashCode() {
      // There's a possibility that either s1 or s2 are nulls  
      if (String.IsNullOrEmpty(s1))
        if (String.IsNullOrEmpty(s2))
          return 0;
        else
          return s2.GetHashCode();
      else if (String.IsNullOrEmpty(s2))
        return s1.GetHashCode();

      // Typical trick: xoring hash codes 
      return s1.GetHashCode() ^ s2.GetHashCode();      
    }

答案 2 :(得分:1)

var v = l1.Where(x =&gt;!l2.Contains(x));