C# 为什么我不能在IEqualityComparer中使用customer.Name.contains(";smith";)lt;客户>;相等法
我想使用HashSet.Contains方法,因为它非常快C# 为什么我不能在IEqualityComparer中使用customer.Name.contains(";smith";)lt;客户>;相等法,c#,iequalitycomparer,C#,Iequalitycomparer,我想使用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. var hashset=n
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.
var hashset=newhashset(customers,newcustomercomparer());
var found=hashset.Contains(新客户{Id=“1234”,Name=“mit”});//“mit”而不是比较器中的“smith”。
我正在搜索customer对象上的多个属性
我必须实现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();
}
}
公共类客户比较:IEqualityComparer
{
公共布尔等于(客户x、客户y)
{
返回x.Id==y.Id&&x.Name.Contains(y.Name);
}
public int GetHashCode(客户对象)
{
返回obj.Id.GetHashCode()^obj.Name.GetHashCode();
}
}
如果我没有在CustomerComparer Equals方法中使用Equals方法,例如.Contains,那么为什么Equals方法从未命中?您实现equality comparer的方式无法正常工作。原因是哈希集和相等比较器在内部的工作方式。当
字典
或哈希集
对项目进行比较时,它将首先对这两个项目调用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));
}
您实现相等比较器的方式无法正常工作。原因是哈希集和相等比较器在内部的工作方式。当
字典
或哈希集
对项目进行比较时,它将首先对这两个项目调用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));
}
为什么当我没有在CustomerComparer Equals方法(如.Contains)中使用Equals方法时,Equals方法从未命中
只有在“customers”集合中至少有一个项与传递给HashSet的Contains方法的Customer对象具有相同的哈希代码时,才会命中Equals方法。如果运行以下示例程序,您将看到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
}
}
公共静态类程序
{
公共类客户
{
公共字符串Id{get;set;}
公共字符串名称{get;set;}
}
公共类客户比较:IEqualityComparer
{
公共布尔等于(客户x、客户y)
{
控制台。WriteLine(“命中!”);
返回x.Id==y.Id&&x.Name.Contains(y.Name);
}
public int GetHashCode(客户对象)
{
返回obj.Id.GetHashCode()^obj.Name.GetHashCode();
}
}
公共静态void Main()
{
列出客户=新列表()
{
新客户(){Id=“1234”,Name=“smith”},
新客户(){Id=“1234”,Name=“mit”}
};
var hashset=new hashset(客户,new CustomerComparer());
var found=hashset.Contains(新客户{Id=“1234”,Name=“mit”});//“mit”,而不是比较器中的等于“smith”。
Console.WriteLine(已找到);/=true
}
}
但如果从“客户”列表中删除第二项,则不会命中Equals方法,因为列表中“smith”客户的哈希代码与传递给Contains方法的“smith”客户的哈希代码不同:
List<Customer> customers = new List<Customer>()
{
new Customer() { Id = "1234", Name = "smith" }
};
列出客户=新列表()
{
新客户(){Id=“1234”,Name=“smith”}
};
为什么当我没有在CustomerComparer Equals方法(如.Contains)中使用Equals方法时,Equals方法从未命中
只有在“customers”集合中至少有一个项与传递给HashSet的Contains方法的Customer对象具有相同的哈希代码时,才会命中Equals方法。如果运行以下示例程序,您将看到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
}
}
公共静态类程序
{
公共类客户
{
公共字符串Id{get;set;}
公共字符串名称{get;set;}
}
公共类客户比较:IEqualityComparer
{
公共布尔等于(客户x、客户y)
{
控制台。WriteLine(“命中!”);
返回x.Id==y.Id&&x.Name.Contains(y.Name);
}
public int GetHashCode(客户对象)
{
返回obj.Id.GetHashCode()^obj.Name.GetHashCode();
}
}
P