我想使用hashset.contains方法,因为它超快。
var hashset = new HashSet<Customer>(customers, new CustomerComparer());
var found = hashset.Contains(new Customer{ Id = "1234", Name = "mit" }); // "mit" instead of an equals "smith" in the comparer.
我正在搜索客户对象上的多个属性。
我必须实现IequalityComparer界面,例如:
public class CustomerComparer : IEqualityComparer<Customer>
{
public bool Equals(Customer x, Customer y)
{
return x.Id == y.Id && x.Name.Contains(y.Name);
}
public int GetHashCode(Customer obj)
{
return obj.Id.GetHashCode() ^ obj.Name.GetHashCode();
}
}
当我不使用quantercomparer内部的等价方法等于.contains之类的方法时,为什么不使用等价方法?
实现平等比较的方式无法正常工作。原因是哈希设置和平等比较在内部工作。当Dictionary
或HashSet
对项目进行比较时,它将首先在这两个项目上调用GetHashCode
。只有当这些哈希代码匹配时,它才能确认与随后拨打Equals
的呼叫的确切匹配,以避免在哈希代码碰撞的情况下进行错误匹配。如果使用示例(x.Name = "smith"
和y.Name = "mit"
),GetHashCode
方法将返回每个项目的不同哈希代码,而Equals
永远不会调用。
在这种情况下,解决方案是仅将Id
用于哈希代码创建。这会降低性能,因为您必须更频繁地致电Equals
来解决碰撞,但这是您必须支付的价格:
public int GetHashCode(Customer obj)
{
return obj.Id.GetHashCode() ;
}
您还应该认为您无法保证您现有的项目是x
还是y
。因此,您必须在两个方向上使用Contains
:
public bool Equals(Customer x, Customer y)
{
return x.Id == y.Id && (x.Name.Contains(y.Name) || y.Name.Contains(x.Name));
}
为什么当我不使用quantercomparer内部的equals方法等于.contains之类的方法?
时,为什么不使用等价方法?
仅当您的"客户"集合中至少存在一个与您传递给标签的方法相同的哈希代码对象的哈希代码中至少有一个物品时,才会击中等价方法。如果运行以下示例程序,您将看到Equals方法确实会受到打击:
public static class Program
{
public class Customer
{
public string Id { get; set; }
public string Name { get; set; }
}
public class CustomerComparer : IEqualityComparer<Customer>
{
public bool Equals(Customer x, Customer y)
{
Console.WriteLine("hit!");
return x.Id == y.Id && x.Name.Contains(y.Name);
}
public int GetHashCode(Customer obj)
{
return obj.Id.GetHashCode() ^ obj.Name.GetHashCode();
}
}
public static void Main()
{
List<Customer> customers = new List<Customer>()
{
new Customer() { Id = "1234", Name = "smith" },
new Customer() { Id = "1234", Name = "mit" }
};
var hashset = new HashSet<Customer>(customers, new CustomerComparer());
var found = hashset.Contains(new Customer { Id = "1234", Name = "mit" }); // "mit" instead of an equals "smith" in the comparer.
Console.WriteLine(found); // = true
}
}
但是,如果您从"客户"列表中删除第二个项目,则不会击中等价方法,因为列表中的"史密斯"客户的哈希码具有与您的"史密斯"客户不同的哈希码传递到包含方法:
List<Customer> customers = new List<Customer>()
{
new Customer() { Id = "1234", Name = "smith" }
};