This test fails:
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
}
Am I misunderstanding something about how a Dictionary
works?
I'm looking for the Java equivalent of .equals()
, not trying to check referential equality.
In Dictionary, the key cannot be null, but value can be. In Dictionary, key must be unique. Duplicate keys are not allowed if you try to use duplicate key then compiler will throw an exception. In Dictionary, you can only store same types of elements.
Equals(Object) Method which is inherited from the Object class is used to check if a specified Dictionary object is equal to another Dictionary object or not. Syntax: public virtual bool Equals (object obj); Here, obj is the object which is to be compared with the current object.
It's a dictionary of dictionaries, so you have 2 keys to access each object, the key for the main dictionary to get you the required sub dictionary, and then the second key for the sub dictionary to get you the required item.
A dictionary, also called an associative array, is a collection of unique keys and a collection of values, where each key is associated with one value. Retrieving and adding values is very fast. Dictionaries take more memory because for each value there is also a key.
Dictionary class does not override Object.Equals
method as seen from MSDN doco:
http://msdn.microsoft.com/en-us/library/bsc2ak47.aspx
Determines whether the specified Object is equal to the current Object.
Seeing that you are doing unit testing, your Assert
class should provide a test method for testing if two collections are the same.
Microsoft Unit testing framework provides CollectionAssert
class for the purpose of comparing collections:
http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.testtools.unittesting.collectionassert_members%28VS.80%29.aspx
EDIT Dictionary implements ICollection
interface, can you see if that just works? You might need to use this overload to compare two dictionary entries.
EDIT Hmm IDictionary does not implement ICollection
, which is a bit of a pain. This however works (albeit a hack):
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);
THe above approach will work for instances of Dictionary
, however if you are testing a method that returns IDictionary
it might fail if the implmentation changes. My advice is to change the code to use Dictionary
instead of IDictionary
(since IDictionary
is not readonly, so you are not hiding all that much by using that instead of concreate Dictionary
).
If you are specifically interested in how you can fix this from unit testing perspective:
Try this
CollectionAssert.AreEquivalent(dict.ToList(), dictClone.ToList());
Explanation
There are extension methods on IDictionary - such as .ToList()
- available in .Net 3.5 and up, which will convert the dictionary into a collection of KeyValuePair that can be easily compared with CollectionAssert.AreEquivalent
.
They'll even give reasonably helpful error messages! Example usage:
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).
The problem is with this line of code:
Assert.AreEqual(dict, dictClone)
You are comparing object references, which aren't equal.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With