我有两个列表A和B,在我的程序开头,它们都填充了数据库中的信息(列表A =列表B)。我的程序运行,使用和修改列表A,列表B保持不变。过了一会儿,我用数据库中的新信息重新加载列表B,然后对列表A进行检查。
foreach (CPlayer player in ListA)
if (ListB.Contains(player))
-----
首先,对象播放器是从类创建的,其主要标识符是player.Name。 如果名称相同,但其他变量不同,.Contains是否仍会返回true?
Class CPlayer(
public CPlayer (string name)
_Name = name
在----我需要使用ListB中导致.Contains返回true的项目,我该怎么做?
答案 0 :(得分:5)
List.Contains
的默认行为是它使用默认的相等比较器。如果您的商品是引用类型,则表示它将使用身份比较,除非您的类通过Equals
提供其他实现。
如果您使用的是.NET 3.5,那么您可以将第二行更改为可以执行所需的操作:
if (ListB.Any(x => x.Name == player.Name))
对于.NET 2.0,您可以为您的类实现Equals
和GetHashCode
,但是如果您不希望两个播放器对象相等,则可能会产生不良行为同名,但在其他领域有所不同。
另一种方法是使Jon Skeet's answer适用于.NET 2.0。创建一个Dictionary<string, object>
并在其中填入listB中所有玩家的名字。然后,为了测试具有特定名称的玩家是否在listB中,您可以使用dict.ContainsKey(name)
。
答案 1 :(得分:2)
Mark的建议的另一种选择是构建一组名称并使用它:
HashSet<string> namesB = new HashSet<string>(ListB.Select(x => x.Name));
foreach (CPlayer player in ListA)
{
if (namesB.Contains(player.Name))
{
...
}
}
答案 2 :(得分:0)
假设您使用的是System.Collections.Generic.List
类,如果CPlayer
类没有实现IEquatable<T>
,它将使用Equals
和GetHashCode
函数{ {1}}类来检查CPlayer
是否有一个等于List
参数的成员。假设您的实现没问题,您可以使用
Contains
从CPlayer listBItem = ListB.First(p => p == player);
答案 3 :(得分:0)
听起来这就是你需要完成的事情:
对于列表A中的每个玩家,找到列表B中具有相同名称的每个玩家,并将两个玩家带入同一范围。
这是一种在查询中连接两个列表的方法:
var playerPairs =
from playerA in ListA
join playerB in ListB on playerA.Name equals playerB.Name
select new { playerA, playerB };
foreach(var playerPair in playerPairs)
{
Console.Write(playerPair.playerA.Name);
Console.Write(" -> ");
Console.WriteLine(playerPair.playerB.Name);
}
答案 4 :(得分:0)
如果你想让.Contains方法只匹配CPlayer.Name,那么在CPlayer类中实现这些方法:
public override bool Equals(object obj)
{
if (!(obj is CPlayer)
return false;
return Name == (obj as CPlayer).Name;
}
public override int GetHashCode()
{
return Name.GetHashCode();
}
如果您希望Name
比较为Case Insensitive,请替换使用此Equals方法:
public override bool Equals(object obj)
{
if (!(obj is CPlayer)
return false;
return Name.Equals((obj as CPlayer).Name, StringComparison.OrdinalIgnoreCase);
}
如果您这样做,您的.Contains调用将按您的意愿运行。 其次,如果要在列表中选择此项,请执行以下操作:
var playerB = ListB[ListB.IndexOf(player)];
它使用相同的.Equals和.GetHashCode方法。
<强> UPD:强> 这可能是一个主观陈述,但如果你的.Equals方法在进行字符串比较之前比较Int哈希值,你也可以从中挤出一些性能。
查看.NET源代码(Reflector FTW)我可以看到,似乎只有HastTable类使用GetHashCode来提高它的性能,而不是每次使用.Equals来比较对象。在像这样的小类的情况下,相等比较器很简单,单个字符串比较..如果你比较所有属性,那么比较两个整数会快得多(特别是如果它们被缓存:))
List.Contains和List.IndexOf不使用哈希码,并使用.Equals方法,因此我建议检查里面的哈希码。它可能不会引起任何注意,但是当你渴望获得每一个ms的执行时(并不总是一件好事,bug嘿!:P)这可能对某人有所帮助。只是说......:)