public class Address{
public string ContactName {get; private set;}
public string Company {get; private set;}
//...
public string Zip {get; private set;}
}
Run Code Online (Sandbox Code Playgroud)
我想实现一个distint地址的概念,所以我重写了Equals()来测试所有字段中不区分大小写的相等性(因为这些是US地址,我使用Ordinal而不是InvariantCulture来获得最大性能):
public override bool Equals(Object obj){
if (obj == null || this.GetType() != obj.GetType())
return false;
Address o = (Address)obj;
return
(string.Compare(this.ContactName, o.ContactName, StringComparison.OrdinalIgnoreCase) == 0) &&
(string.Compare(this.Company, o.Company, StringComparison.OrdinalIgnoreCase) == 0)
// ...
(string.Compare(this.Zip, o.Zip, StringComparison.OrdinalIgnoreCase) == 0)
}
Run Code Online (Sandbox Code Playgroud)
我想像这样写一个GetHashCode()(暂时忽略连接效率低下):
public override int GetHashCode(){
return (this.contactName + this.address1 + this.zip).ToLowerOrdinal().GetHashCode();
}
Run Code Online (Sandbox Code Playgroud)
但那不存在.我应该用什么呢?或者我应该在我的Equals()方法中使用InvariantCulture?
(我在想.ToLowerInvariant().GetHashCode(),但我不能100%确定InvariantCulture不能确定相同的字符(例如重音)在另一个上下文中具有不同的含义.)
ben*_*ben 24
无论你使用什么字符串比较方法Equals(),使用相同的方法都是有意义的GetHashCode().
不需要仅为计算哈希码创建临时字符串.对于StringComparison.OrdinalIgnoreCase,使用StringComparer.OrdinalIgnoreCase.GetHashCode()
然后,您需要将多个哈希码合并为一个.XOR应该没问题(因为一个人的邮政编码不太可能是另一个人的联系人姓名).然而,纯粹主义者可能不同意.
public override int GetHashCode()
{
return StringComparer.OrdinalIgnoreCase.GetHashCode(ContactName) ^
StringComparer.OrdinalIgnoreCase.GetHashCode(Company) ^
// ...
StringComparer.OrdinalIgnoreCase.GetHashCode(Zip);
}
Run Code Online (Sandbox Code Playgroud)
说了这么多之后,我会质疑使用像Address这样的复合结构作为字典的关键是否合理.但这个原则适用于身份类型的字符串.
Joe*_*tro 15
两个不相等的对象可以具有相同的哈希码.虽然两个相等的对象永远不应该有不同的哈希码.如果你使用InvariantCulture作为你的哈希码,那么如果用OrdinalIgnoreCase实现的话,Equals的合同就会是正确的.
从StringComparer.OrdinalIgnoreCase(强调我的)的文档:
http://msdn.microsoft.com/en-us/library/system.stringcomparer.ordinalignorecase.aspx
OrdinalIgnoreCase属性返回的StringComparer将字符串中的字符进行比较,就像使用不变文化的约定将它们转换为大写一样,然后执行独立于语言的简单字节比较.在比较以编程方式生成的字符串或比较不区分大小写的资源(如路径和文件名)时,这是最合适的.
现在您可以使用System.HashCode
public class Address
{
public string ContactName { get; private set; }
public string Company { get; private set; }
// ...
public string Zip { get; private set; }
public override bool Equals(object obj)
{
return
obj is Address address &&
string.Equals(ContactName, address.ContactName, StringComparison.OrdinalIgnoreCase) &&
string.Equals(Company, address.Company, StringComparison.OrdinalIgnoreCase) &&
// ...
string.Equals(Zip, address.Zip, StringComparison.OrdinalIgnoreCase);
}
public override int GetHashCode()
{
var hash = new HashCode();
hash.Add(ContactName, StringComparer.OrdinalIgnoreCase);
hash.Add(Company, StringComparer.OrdinalIgnoreCase);
// ...
hash.Add(Zip, StringComparer.OrdinalIgnoreCase);
return hash.ToHashCode();
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4193 次 |
| 最近记录: |