编程语言
首页 > 编程语言> > c# – IEquatable的类实现,用作字典中的键

c# – 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);
    }
}

但是,我似乎仍然无法在我的字典中查找项目.此外,以下测试失败:

    [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);
    }

有人能够指出我出错的地方吗?我确定我错过了一些相当简单的东西,但我不确定是什么.

解决方法:

您的类必须重写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;
        }
    }
}

请注意,我还根据以下内容改进了GetHashCode算法:What is the best algorithm for an overridden 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;
        }
    }                      
}

现在这个工作,并不要求CoinDetails覆盖Equals GetHashCode:

var dict = new Dictionary<CoinDetails, string>(new CoinComparer());
dict.Add(new CoinDetails("1POUND", "1997"), "");
dict.Add(new CoinDetails("1POUND", "1997"), ""); // FAIL!!!!

标签:c,dictionary,hashcode,iequatable
来源: https://codeday.me/bug/20190517/1120261.html