use*_*789 6 c# dictionary hashcode iequatable
我有一个由两个字符串和一个枚举组成的类.我正在尝试将此类的实例用作字典中的键.不幸的是,我似乎没有正确实现IEquatable.这是我如何做到的:
public enum CoinSide
{
Heads,
Tails
}
public class CoinDetails : IComparable, IEquatable<CoinDetails>
{
private string denomination;
private string design;
private CoinSide side;
//...
public int GetHashCode(CoinDetails obj)
{
return string.Concat(obj.Denomination, obj.Design, obj.Side.ToString()).GetHashCode();
}
public bool Equals(CoinDetails other)
{
return (this.Denomination == other.Denomination && this.Design == other.Design && this.Side == other.Side);
}
}
Run Code Online (Sandbox Code Playgroud)
但是,我似乎仍然无法在我的字典中查找项目.此外,以下测试失败:
[TestMethod]
public void CoinDetailsHashCode()
{
CoinDetails a = new CoinDetails("1POUND", "1997", CoinSide.Heads);
CoinDetails b = new CoinDetails("1POUND", "1997", CoinSide.Heads);
Assert.AreEqual(a.GetHashCode(), b.GetHashCode());
}
[TestMethod]
public void CoinDetailsCompareForEquality()
{
CoinDetails a = new CoinDetails("1POUND", "1997", CoinSide.Heads);
CoinDetails b = new CoinDetails("1POUND", "1997", CoinSide.Heads);
Assert.AreEqual<CoinDetails>(a, b);
}
Run Code Online (Sandbox Code Playgroud)
有人能够指出我出错的地方吗?我确定我错过了一些相当简单的东西,但我不确定是什么.
你的类必须覆盖Equals和GetHashCode:
public class CoinDetails
{
private string Denomination;
private string Design;
private CoinSide Side;
public override bool Equals(object obj)
{
CoinDetails c2 = obj as CoinDetails;
if (c2 == null)
return false;
return Denomination == c2.Denomination && Design == c2.Design;
}
public override int GetHashCode()
{
unchecked
{
int hash = 17;
hash = hash * 23 + (Denomination ?? "").GetHashCode();
hash = hash * 23 + (Design ?? "").GetHashCode();
return hash;
}
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,我还GetHashCode根据以下内容改进了算法:重写的System.Object.GetHashCode的最佳算法是什么?
您还可以将自定义传递IEqualityComparer<CoinDetail>给字典:
public class CoinComparer : IEqualityComparer<CoinDetails>
{
public bool Equals(CoinDetails x, CoinDetails y)
{
if (x == null || y == null) return false;
if(object.ReferenceEquals(x, y)) return true;
return x.Denomination == y.Denomination && x.Design == y.Design;
}
public int GetHashCode(CoinDetails obj)
{
unchecked
{
int hash = 17;
hash = hash * 23 + (obj.Denomination ?? "").GetHashCode();
hash = hash * 23 + (obj.Design ?? "").GetHashCode();
return hash;
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在这可以工作,不需要CoinDetails覆盖Equals+ GetHashCode:
var dict = new Dictionary<CoinDetails, string>(new CoinComparer());
dict.Add(new CoinDetails("1POUND", "1997"), "");
dict.Add(new CoinDetails("1POUND", "1997"), ""); // FAIL!!!!
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4739 次 |
| 最近记录: |