.net LINQ中的DefaultEquality比较器
我有以下代码.net LINQ中的DefaultEquality比较器,.net,comparison,.net,Comparison,我有以下代码 using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; namespace ConsoleApplication2 { class Program { static void Main(string[] args) { List<I> bars = new List&l
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
List<I> bars = new List<I>();
bars.Add(new A() { Id = 1 });
bars.Add(new B() { Id = 1 });
bars.Add(new A() { Id = 1 });
var distictBars = bars.Distinct();
foreach (var item in distictBars)
{
Debug.WriteLine(item.Name);
}
}
}
interface I
{
string Name { get; }
}
class Base
{
public int Id { get; set; }
}
class A : Base, I, IEquatable<A>
{
public string Name
{
get { return this.Id + "-A"; }
}
public bool Equals(A other)
{
return this.Id == other.Id;
}
public override bool Equals(object obj)
{
if (obj is A)
return this.Equals(obj as A);
else
return object.ReferenceEquals(this, obj);
}
}
class B : Base, I, IEquatable<B>
{
public string Name
{
get { return this.Id + "-B"; }
}
public bool Equals(B other)
{
return this.Id == other.Id;
}
public override bool Equals(object obj)
{
if (obj is A)
return this.Equals(obj as A);
else
return object.ReferenceEquals(this, obj);
}
}
}
不过,我需要以下几点
1-A
1-B
1-A
1-A
1-B
也就是说,消除类型A或B的重复项。Distinct
LINQ方法似乎没有考虑我的Equals覆盖,也没有考虑IEquitable接口实现
除了该方法进行指定的比较外,我应该如何按顺序进行?该
Distinct
方法可能会在内部使用类似于哈希集的东西,它依赖于哈希代码(显然)。您还需要覆盖GetHashCode
在我看来,你总的来说有一些不必要的重复。您的A
和B
类在确定相等性方面具有基本相同的逻辑;如果两个Base
对象的ID相等且类型相同,您希望确保它们相等吗?(在我看来就是这样;在本例中,您的实现似乎包含几个错误,但这仍然是我最好的猜测。)
如果是这样,只需使Base
实现IEquatable
,您的A
和B
实现就会变得简单得多:
class Base : IEquatable<Base>
{
public Base(int id)
{
Id = id;
}
public int Id { get; private set; }
public bool Equals(Base other)
{
if (other == null)
{
return false;
}
// Ensure As only compare equal with other As
// and the same for Bs (and potentially other subtypes).
return other.GetType().Equals(GetType()) && other.Id == Id;
}
public override bool Equals(object other)
{
if (other is Base)
{
return Equals((Base)other);
}
return false;
}
public override int GetHashCode()
{
return Id;
}
}
class A : Base, I
{
public A(int id) : base(id)
{ }
public string Name
{
get { return this.Id + "-A"; }
}
}
class B : Base, I
{
public B(int id) : base(id)
{ }
public string Name
{
get { return this.Id + "-B"; }
}
}
Distinct
方法可能会在内部使用类似于HashSet
的东西,它依赖于散列码(显然)。您还需要覆盖GetHashCode
在我看来,你总的来说有一些不必要的重复。您的A
和B
类在确定相等性方面具有基本相同的逻辑;如果两个Base
对象的ID相等且类型相同,您希望确保它们相等吗?(在我看来就是这样;在本例中,您的实现似乎包含几个错误,但这仍然是我最好的猜测。)
如果是这样,只需使Base
实现IEquatable
,您的A
和B
实现就会变得简单得多:
class Base : IEquatable<Base>
{
public Base(int id)
{
Id = id;
}
public int Id { get; private set; }
public bool Equals(Base other)
{
if (other == null)
{
return false;
}
// Ensure As only compare equal with other As
// and the same for Bs (and potentially other subtypes).
return other.GetType().Equals(GetType()) && other.Id == Id;
}
public override bool Equals(object other)
{
if (other is Base)
{
return Equals((Base)other);
}
return false;
}
public override int GetHashCode()
{
return Id;
}
}
class A : Base, I
{
public A(int id) : base(id)
{ }
public string Name
{
get { return this.Id + "-A"; }
}
}
class B : Base, I
{
public B(int id) : base(id)
{ }
public string Name
{
get { return this.Id + "-B"; }
}
}
您需要覆盖对象中的.GetHashCode()
。我建议这样做:
public override int GetHashCode() {
return this.Id;
}
您需要覆盖对象中的.GetHashCode()
。我建议这样做:
public override int GetHashCode() {
return this.Id;
}
覆盖GetHashCode。。。我该怎么回那里?身份证?@serhio:当然可以。如果两个对象相等,那么GetHashCode()应该返回相同的值。由于ID是唯一要比较的对象,因此返回此.ID.GetHashCode()。如果要比较更多,则对所有比较字段的GetHashCode()值进行异或运算。@mattmc3:Int32.GetHashCode()只返回整数@塞里奥:我就是这么说的,不是吗?您当前的实现可能会进入一个无限递归循环(这将使堆栈溢出)。所以,我需要实现IEquatable吗?重写GetHashCode。。。我该怎么回那里?身份证?@serhio:当然可以。如果两个对象相等,那么GetHashCode()应该返回相同的值。由于ID是唯一要比较的对象,因此返回此.ID.GetHashCode()。如果要比较更多,则对所有比较字段的GetHashCode()值进行异或运算。@mattmc3:Int32.GetHashCode()只返回整数@塞里奥:我就是这么说的,不是吗?您当前的实现可能会进入无限递归循环(这将使堆栈溢出)。因此,我需要实现IEquatable吗?