我在KeyValuePair中有一个类,IEquatable的实现不像我预期的那样工作。我的单元测试失败了。我想知道为什么测试失败?
类:
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();
}
}测试:
[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()失败
发布于 2019-07-25 12:56:43
您的Equals()实现不够深入。因为:
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()逻辑,例如:
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实现)
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有相同的哈希码吗?=>真
然后,在你的课堂上,你会看到这样的东西:
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()实现)
和:
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实例是否相等?=>真
https://stackoverflow.com/questions/57143171
复制相似问题