0

是否可以在对象实例不一定相同但在功能上等效的对象列表上执行联合/除外?

我的意思是,如果我有这样的课,

Class A
{
    String a;
    int b;
    double c;
}

我有以下列表:

A foo = new A() {"a",2,3.4}    
A bar = new A() {"a",2,3.4}

List<A> firstList = new List<A>() { foo }
List<A> secondList = new List<A>() { bar }

如果 firstList 和 secondList 具有完全不同的对象实例但对象的字段/属性完全相同,我如何在 secondList 上执行 firstList.Except/Union?

4

4 回答 4

1

您需要重载Equals类的方法。

现在,它检查相等性的方法是检查引用。有一种方法可以解决这个问题,通过覆盖该Equals方法:

class A
{
    string a;
    int b;
    double c;
    public override bool Equals(object obj)
    {
        A aobj = obj as A;
        if (aobj == null) return false;
        return a == aobj.a && b == aobj.b && c == aobj.c;
    }
}

但是,为了使这些函数发挥最佳性能,您还需要重写该GetHashCode方法。像这样:

class A
{
    string a;
    int b;
    double c;
    public override bool Equals(object obj)
    {
        return a == obj.a && b == obj.b && c == obj.c;
    }
    public override int GetHashCode()
    {
        unchecked { return 17 * (a ?? "").GetHashCode() * b * c.GetHashCode(); }
    }
}
于 2013-07-03T18:17:58.810 回答
1

只需重写该object.Equals方法即可告诉世界何时平等对待您的对象。你class A应该看起来像这样:

class A
{
    string a;
    int b;
    double c;

    public override bool Equals(object obj)
    {
        if (!(obj is A)) return obj.Equals(this); // defer to other object
        A other = (A)obj;
        return a == other.a && b == other.b && c == other.c; // check field equality
    }
    public override int GetHashCode()
    {
        int hc = 13;
        hc += a.GetHashCode() * 27;
        hc += b.GetHashCode() * 27;
        hc += c.GetHashCode() * 27;
    }
}
于 2013-07-03T18:18:09.703 回答
0

在以前的答案中添加更多内容。覆盖 Equals 将需要覆盖 == 和 !=

public class A
{
    String a;
    int b;
    double c;

    public override bool Equals(object obj)
    {   
        if (object.ReferenceEquals(null, obj))
        {
            return false;
        }

        if (object.ReferenceEquals(this, obj))
        {
            return true;
        }

        if (obj.GetType() != typeof(A))
        {
            return false;
        }

        var other = obj as A;
        return string.Equals(this.a, other.a) && this.b == other.b && this.c == other.b;
    }

    public override int GetHashCode()
    {
        if (string.IsNullOrEmpty(a))
        {
            return this.b.GetHashCode() ^ this.c.GetHashCode();
        }
        return this.a.GetHashCode() ^ this.b.GetHashCode() ^ this.c.GetHashCode();
    }

    public static bool operator ==(A left, A right)
    {
        if (object.ReferenceEquals(left, right))
        {
            return true;
        }

        if (object.ReferenceEquals(null, left))
        {
            return false;
        }

        if (object.ReferenceEquals(null, right))
        {
            return false;
        }

        return left.Equals(right);
    }

    public static bool operator !=(A left, A right)
    {
        return !(left == right);
    }
}
于 2013-07-03T18:26:13.520 回答
0

您可以使用 LINQ to Objects 在列表上创建交集和并集 - 无需覆盖 Equals 和 GetHashCode。使用Enumerable.IntersectEnumerable.Except方法:

public class A
{
    public String a;
    public int b;
    public double c;
}
A foo = new A() {a = "a", b = 2, c = 3.4};
A bar = new A() {a = "a", b = 2, c = 3.4};

List<A> firstList = new List<A>() { foo };
List<A> secondList = new List<A>() { bar };

firstList.Except(secondList);
firstList.Intersect(secondList);

这种情况下的输出是:

same entries: 
>> IEnumerable<A> (1 item) 4  
>> a b c 
>> a 2 3,4 

您可以组合 firstList.Method(secondsList) ,反之亦然。您可以编写一个自定义的比较器 - IEqualityComparer以比较复杂的对象类型。

于 2013-07-03T18:41:37.390 回答