是否可以在对象列表中执行union / except,其中对象的实例不一定相同但功能相同?
我的意思是,如果我有这样的课程,
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?
答案 0 :(得分: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(); }
}
}
答案 1 :(得分: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;
}
}
答案 2 :(得分:0)
为以前的答案添加更多内容。覆盖等于将需要覆盖==和!=
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);
}
}
答案 3 :(得分:0)
您可以使用LINQ to Objects在列表上创建交叉点和联合 - 并且不需要重写Equals和GetHashCode。使用Enumerable.Intersect和Enumerable.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),反之亦然。 您可以事件编写custom Comparer - IEqualityComparer以比较复杂对象类型。