【发布时间】:2018-06-22 07:03:04
【问题描述】:
我正在尝试比较两个对象集合,它们在各自的集合中具有完全相同的对象。为此,我为 ContainsExactly 编写了一个扩展方法。
但是,我遇到了一个问题,即即使它们是集合也不相同。下面是测试代码:
public static bool ContainsExactly<T>(this List<T> set1, List<T> set2)
{
if (set1.Count != set2.Count)
return false;
//var isEqual = new HashSet<T>(set1).SetEquals(set2); original test just returned isEqual
var result = set1.Except(set2);
return !result.Any(); //still yields both collections in result
}
那么我就有了我的对象:
public class ReferenceClassObjectTest : IEquatable<ReferenceClassObjectTest>
{
public int Id { get; set; }
public TestObject TestObject { get; set; }
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((ReferenceClassObjectTest)obj);
}
public bool Equals(ReferenceClassObjectTest other)
{
var casted = other as ReferenceClassObjectTest;
if (casted == null)
return false;
return Id == casted.Id && TestObject == casted.TestObject;
}
public override int GetHashCode()
{
var hash = Id;
if(TestObject != null)
{
hash = (hash * 397) ^ TestObject.GetHashCode();
}
else
{
hash = (hash * 397);
}
return hash;
}
}
public class TestObject : IEquatable<TestObject>
{
public int Id { get; set; }
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((TestObject)obj);
}
public bool Equals(TestObject other)
{
var casted = other as TestObject;
if (casted == null)
return false;
return Id == casted.Id;
}
public override int GetHashCode()
{
var hashCode = Id;
hashCode = (hashCode * 397);
return hashCode;
}
}
当我运行测试时,它们仍然返回 false:
var set2 = new List<ReferenceClassObjectTest>()
{
new ReferenceClassObjectTest
{
Id = 1,
TestObject = new TestObject
{
Id = 2
}
},
new ReferenceClassObjectTest
{
Id = 2,
TestObject = new TestObject
{
Id = 3
}
},
};
var set3 = new List<ReferenceClassObjectTest>()
{
new ReferenceClassObjectTest
{
Id = 1,
TestObject = new TestObject
{
Id = 2
}
},
new ReferenceClassObjectTest
{
Id = 2,
TestObject = new TestObject
{
Id = 3
}
},
};
Assert.IsTrue(set2.ContainsExactly(set3));
任何关于为什么即使在覆盖 GetHashCode() 时它们也不能正确比较的见解?
我认为 HashSet.SetEquals() 会考虑我对 GetHashCode() 的覆盖,当我在列表中的两个单独对象上调用 get hashcode 时,我确实得到了相同的哈希值:。
set3[1].TestObject.GetHashCode() 第1191章
set2[1].TestObject.GetHashCode() 第1191章
set2[0].GetHashCode() 663
set3[0].GetHashCode() 663
【问题讨论】:
-
我就坐在你旁边,但我不会亲自帮助你,而是在这里回答。 #introvertpowers
-
我不知道你是谁?!
-
为什么在你的
Equals实现中使用casted和as?我不相信other可能不是正确的类型...
标签: c# .net contains iequatable