这是我的客户类:
public class Clients
{
public string Email { get; set; }
public string Name { get; set; }
public Clients(string e, string n)
{
Email = e;
Name = n;
}
我想创建一个包含列表A和列表B中相同客户端的新列表。 例如: 名单A - 约翰,乔纳森,詹姆斯...... 名单B - 玛莎,简,乔纳森...... 取消订阅者 - 乔纳森
public static List<Clients> SameClients(List<Clients> A, List<Clients> B)
{
List<Clients> Unsubscribers = new List<Clients>();
Unsubscribers = A.Intersect(B).ToList();
return Unsubscribers;
}
然而由于某些原因,我得到空列表,我不知道错误是什么。
答案 0 :(得分:4)
问题在于,当您比较对象时,Equals
和Gethashcode
用于比较它们。你可以覆盖这两种方法,并根据你的需要提供你自己的实现......下面已经有一个答案,涵盖了如何覆盖这两种方法
然而,通常我更喜欢保持我的实体/模型(或任何你想要称之为它们)非常简单,并保持比较实现细节远离我的模型。在这种情况下,您可以实施IEqualityComparer<TSource>
并使用Intersects
的重载来接收IEqualityComparer
以下是IEqualityComprarer
仅基于Name
属性的示例实现...
public class ClientNameEqualityComparer : IEqualityComparer<Clients>
{
public bool Equals(Clients c1, Clients c2)
{
if (c2 == null && c1 == null)
return true;
else if (c1 == null | c2 == null)
return false;
else if(c1.Name == c2.Name)
return true;
else
return false;
}
public int GetHashCode(Client c)
{
return c.Name.GetHashCode();
}
}
基本上,上面的实现仅关注Name
属性,如果Clients
的两个实例具有Name
属性的相同值,则它们被认为是相等的。
现在你可以做以下了......
A.Intersect(B, new ClientNameEqualityComparer()).ToList();
这将产生你期待的结果......
答案 1 :(得分:1)
Intersect
使用GetHashCode
和Equals
,但您没有覆盖它,因此Object.Equals
仅使用compares references。由于所有客户端实例都使用new
进行初始化,因此即使它们具有相同的值,它们也是单独的实例。这就是Intersect
“认为”没有共同客户的原因。
所以你有几个选择。
IEqualityComparer<Clients>
并将其传递给Intersect
(或许多其他LINQ方法)。这样做的好处是,您可以针对不同的要求实现不同的比较器,而不需要修改原始类Clients
覆盖Equals
和GetHashCode
和/或Clients
实施IEquatable<Clients>
例如(显示最后两个,因为其他答案已显示IEqualityComparer<T>
):
public class Clients : IEquatable<Clients>
{
public string Email { get; set; }
public string Name { get; set; }
public Clients(string e, string n)
{
Email = e;
Name = n;
}
public override bool Equals(object obj)
{
return obj is Clients && this.Equals((Clients)obj);
}
public bool Equals(Clients other)
{
return Email == other?.Email == true
&& Name == other?.Name == true;
}
public override int GetHashCode()
{
unchecked
{
int hash = 17;
hash = hash * 23 + (Email?.GetHashCode() ?? 0);
hash = hash * 23 + (Name?.GetHashCode() ?? 0);
return hash;
}
}
}
值得一读: