C# 具有不同对象实例的列表上的并集/例外

C# 具有不同对象实例的列表上的并集/例外,c#,.net,linq,enumerable,C#,.net,Linq,Enumerable,在对象实例不一定相同但功能等效的对象列表上,是否可以执行并集/例外 我的意思是如果我有这样的课 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 =

在对象实例不一定相同但功能等效的对象列表上,是否可以执行并集/例外

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

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 }
A foo=newa(){“A”,2,3.4}
A条=新的A(){“A”,2,3.4}
List firstList=新列表(){foo}
List secondList=新列表(){bar}
如果firstList和secondList具有完全不同的对象实例,但对象的字段/属性完全相同,如何在secondList上执行firstList.Exception/Union

您需要重载类的方法

现在,它检查相等性的方法是检查引用。有一种方法可以解决这个问题,方法是重写
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;
    }
}
但是,要使这些函数发挥最佳性能,还需要重写该方法。像这样:

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(); }
    }
}

只需重写
object.Equals
方法,告诉世界何时平等对待对象。您的
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;
    }
}

对前面的答案再补充一点。重写等于将需要重写==和=

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);
    }
}

您可以使用LINQ to对象在列表上创建交点和并集,而无需重写Equals和GetHashCode。使用以下步骤和方法:

公共A类
{
公共字符串a;
公共int b;
公共双c;
}
A foo=newa(){A=“A”,b=2,c=3.4};
A条=新的A(){A=“A”,b=2,c=3.4};

列表以比较复杂的对象类型。

覆盖
对象.Equals()
方法如何?然后,所有检查相等性的Linq方法都将使用您的方法,该方法应基于字段检查相等性。如果您重写
Equals
方法,则还应重写
GetHashCode
方法。实际上,我会将其添加为一个答案。您在get hash code函数中没有对
b
进行哈希运算。另外,乘以17在这里并没有任何作用,你可以删除它;类
对象
没有字段
a
b
c
。@Servy b是一个
int
int
GetHashCode
返回此值仅供参考:
int.GetHashCode
是无用的。它是
返回这个@newStackExchangeInstance meh,这并不重要。它还依赖于实现,因此最好使用
GetHashCode
方法。@newStackExchangeInstance您不应该依赖于特定的实现。然而,正如我已经说过的,这并不重要。如果你想编辑它,我不在乎。不,不在乎。然而,这是预期的行为。我的意思是,一般来说,实现==!=是良好的做法;否则,基于如何检查相等性,您不会得到不一致的结果吗?因此,您使用匿名对象四处走动?浪费资源。
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