首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >EqualityComparer for KeyValuePair的问题

EqualityComparer for KeyValuePair的问题
EN

Stack Overflow用户
提问于 2019-07-22 09:38:52
回答 1查看 191关注 0票数 0

我在KeyValuePair中有一个类,IEquatable的实现不像我预期的那样工作。我的单元测试失败了。我想知道为什么测试失败?

类:

代码语言:javascript
复制
public class MyClass : IEquatable<MyClass>
{
    public KeyValuePair<int[], string> KeyValuePair { get; set; }

    public override bool Equals(object obj)
    {
        return Equals(obj as MyClass);
    }

    public bool Equals(MyClass other)
    {
        return other != null &&
               EqualityComparer<KeyValuePair<int[], string>>.Default.Equals(KeyValuePair, other.KeyValuePair);
    }

    public override int GetHashCode()
    {
        var hash = new HashCode();
        hash.Add(KeyValuePair);
        return hash.ToHashCode();
    }
}

测试:

代码语言:javascript
复制
[Fact]
    public void Test1()
    {
        MyClass expectedObject = new MyClass()
        {
            KeyValuePair = new KeyValuePair<int[], string>(new int[] { 1 }, "abc")
        };
        MyClass actualObject = new MyClass()
        {
            KeyValuePair = new KeyValuePair<int[], string>(new int[] { 1 }, "abc")
        };
        Assert.Equal(expectedObject, actualObject);
    }

测试结果:

消息: Assert.Equal()失败

EN

回答 1

Stack Overflow用户

发布于 2019-07-25 12:56:43

您的Equals()实现不够深入。因为:

代码语言:javascript
复制
Console.WriteLine("Are two int[] arrays equal? => "+
     EqualityComparer<int[]>.Default.Equals(new int[] { 1 }, new int[] { 1 }));

Console.WriteLine("Do two int[] have the same hashcode? => " +
     (new int[] { 1 }.GetHashCode() == new int[] { 1 }.GetHashCode()));

两个int[]数组是否相等?=> False 两个int[]有相同的哈希码吗?=> False

您还必须为Equals()数组实现int[]GetHashCode()逻辑,例如:

代码语言:javascript
复制
public class EquatableIntArray : IEquatable<EquatableIntArray>
{
    public int[] Items { get; set; }

    public EquatableIntArray(int[] Items)
    {
        this.Items = Items;
    }

    public override bool Equals(object obj)
    {
        return Equals(obj as EquatableIntArray);
    }

    public bool Equals(EquatableIntArray other)
    {
        if (other == null) return false;
        if (ReferenceEquals(this, other)) return true;
        return other.Items != null && (this.Items?.SequenceEqual(other.Items)??false);
    }

    private int? cachedHashCode;

    public override int GetHashCode()
    {
        if (cachedHashCode.HasValue) return cachedHashCode.Value;
        int hc = Items.Length;
        for (int i = 0; i < Items.Length; ++i)
        {
            hc = unchecked(hc * 314159 + Items[i]);
        }
        return (cachedHashCode = hc).Value;
    }
}

(以上是GetHashCode()here实现)

代码语言:javascript
复制
Console.WriteLine("Are two EquatableIntArrays equal? => " +
     EqualityComparer<EquatableIntArray>.Default.Equals(
         new EquatableIntArray(new int[] { 1 })
       , new EquatableIntArray(new int[] { 1 })));

 Console.WriteLine("Do two EquatableIntArrays have the same hashcode? => " +
      (new EquatableIntArray(new int[] { 1 }).GetHashCode()
    == new EquatableIntArray(new int[] { 1 }).GetHashCode()));

两个EquatableIntArrays相等吗?=>真 两个EquatableIntArrays有相同的哈希码吗?=>真

然后,在你的课堂上,你会看到这样的东西:

代码语言:javascript
复制
public class MyClass2 : IEquatable<MyClass2>
{
    public KeyValuePair<EquatableIntArray, string> KeyValuePair { get; set; }

    public override bool Equals(object obj)
    {
        return Equals(obj as MyClass2);
    }

    public bool Equals(MyClass2 other)
    {
        return other != null &&
               EqualityComparer<KeyValuePair<EquatableIntArray, string>>.Default.Equals(KeyValuePair, other.KeyValuePair);
    }
    private int? cachedHashCode;
    public override int GetHashCode()
    {
        if (cachedHashCode.HasValue) return cachedHashCode.Value;
        cachedHashCode = CombineHashCodes(KeyValuePair.Key.GetHashCode(), KeyValuePair.Value.GetHashCode());
        return cachedHashCode.Value;
    }

    internal static int CombineHashCodes(int h1, int h2)
    {
        return (((h1 << 5) + h1) ^ h2);
    }
}

(我在.NET Framework4.7上进行了测试,那里没有HashCode类,所以我从Tuple那里借用了GetHashCode()实现)

和:

代码语言:javascript
复制
MyClass2 expectedObject2 = new MyClass2()
{
  KeyValuePair = new KeyValuePair<EquatableIntArray, string>(new EquatableIntArray(new int[] { 1 }), "abc")
};
MyClass2 actualObject2 = new MyClass2()
{
   KeyValuePair = new KeyValuePair<EquatableIntArray, string>(new EquatableIntArray(new int[] { 1 }), "abc")
};

Console.WriteLine("Are two MyClass2 instances equal? => "+ expectedObject2.Equals(actualObject2));

两个MyClass2实例是否相等?=>真

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57143171

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档