此测试失败:
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestMethod()]
public void dictEqualTest() {
IDictionary<string, int> dict = new Dictionary<string, int>();
IDictionary<string, int> dictClone = new Dictionary<string, int>();
for (int x = 0; x < 3; x++) {
dict[x.ToString()] = x;
dictClone[x.ToString()] = x;
}
Assert.AreEqual(dict, dictClone); // fails here
Assert.IsTrue(dict.Equals(dictClone)); // and here, if the first is commented out
Assert.AreSame(dict, dictClone); // also fails
}
我是否误解了Dictionary
如何运作?
我正在寻找等价于.equals()
的Java,而不是试图检查引用相等。
答案 0 :(得分:21)
字典类不会覆盖从MSDN doco中看到的Object.Equals
方法:
http://msdn.microsoft.com/en-us/library/bsc2ak47.aspx
确定是否指定 Object等于当前的Object。
看到你正在进行单元测试,你的 Assert
类应该提供一个测试方法来测试两个集合是否相同。
Microsoft单元测试框架提供CollectionAssert
类用于比较集合:
编辑字典实现ICollection
界面,你能看出它是否有效吗?您可能需要使用this overload来比较两个字典条目。
编辑 Hmm IDictionary没有实现ICollection
,这有点痛苦。然而,这有效(虽然是黑客):
IDictionary<string, int> dict = new Dictionary<string, int>();
IDictionary<string, int> dictClone = new Dictionary<string, int>();
for(int x = 0; x < 3; x++) {
dict[x.ToString()] = x;
dictClone[x.ToString()] = x;
}
CollectionAssert.AreEqual((System.Collections.ICollection)dict, (System.Collections.ICollection)dictClone);
上述方法适用于Dictionary
的实例,但是如果您正在测试返回IDictionary
的方法,则如果该实施更改,则可能会失败。我的建议是将代码更改为使用Dictionary
而不是IDictionary
(因为IDictionary
不是只读的,因此您不会通过使用它代替concreate {{1}来隐藏所有这些})。
答案 1 :(得分:9)
如果您对如何从单元测试角度解决此问题特别感兴趣:
试试这个
CollectionAssert.AreEquivalent(dict.ToList(), dictClone.ToList());
<强>解释强>
有extension methods on IDictionary - 例如.ToList()
- 可在.Net 3.5及更高版本中使用,它会将字典转换为KeyValuePair的集合,可以轻松地与CollectionAssert.AreEquivalent
进行比较。
他们甚至会提供合理有用的错误消息!用法示例:
IDictionary<string, string> d1 = new Dictionary<string, string> {
{ "a", "1"}, {"b", "2"}, {"c", "3"}};
IDictionary<string, string> d2 = new Dictionary<string, string> {
{"b", "2"}, { "a", "1"}, {"c", "3"}}; // same key-values, different order
IDictionary<string, string> d3 = new Dictionary<string, string> {
{ "a", "1"}, {"d", "2"}, {"c", "3"}}; // key of the second element differs from d1
IDictionary<string, string> d4 = new Dictionary<string, string> {
{ "a", "1"}, {"b", "4"}, {"c", "3"}}; // value of the second element differs from d1
CollectionAssert.AreEquivalent(d1.ToList(), d2.ToList());
//CollectionAssert.AreEquivalent(d1.ToList(), d3.ToList()); // fails!
//CollectionAssert.AreEquivalent(d1.ToList(), d4.ToList()); // fails!
// if uncommented, the 2 tests above fail with error:
// CollectionAssert.AreEquivalent failed. The expected collection contains 1
// occurrence(s) of <[b, 2]>. The actual collection contains 0 occurrence(s).
答案 2 :(得分:7)
问题在于这行代码:
Assert.AreEqual(dict, dictClone)
您正在比较不相等的对象引用。
答案 3 :(得分:4)
我使用了一种扩展方法来检查两个序列是否相等
public static bool CheckForEquality<T>(this IEnumerable<T> source, IEnumerable<T> destination)
{
if (source.Count() != destination.Count())
{
return false;
}
var dictionary = new Dictionary<T, int>();
foreach (var value in source)
{
if (!dictionary.ContainsKey(value))
{
dictionary[value] = 1;
}
else
{
dictionary[value]++;
}
}
foreach (var member in destination)
{
if (!dictionary.ContainsKey(member))
{
return false;
}
dictionary[member]--;
}
foreach (var kvp in dictionary)
{
if (kvp.Value != 0)
{
return false;
}
}
return true;
}
答案 4 :(得分:1)
您完全不了解参考类型的工作原理。
Dictionary
不会覆盖object.Equals()
。因此,它使用引用相等 - 基本上,如果两个引用都指向同一个实例,它们是相等的,否则它们不是。
答案 5 :(得分:0)
NUnit类CollectionAssert
有一个AreEquivalent
method which accepts IEnumerable
as parameters,所以在这种情况下它就像
CollectionAssert.AreEquivalent(dict, dictClone);
因为Dictionary
实现了IEnumerable
。