Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is a Dictionary's order the same if it has exactly the same content?

I know that the order of a dictionary is undefined, MSDN says so:

For purposes of enumeration, each item in the dictionary is treated as a KeyValuePair structure representing a value and its key. The order in which the items are returned is undefined.

Thats fine, but if I have two instances of a dictionary, each with the same content, will the order be the same?

I'm guessing so because as I understand, the order is determined by the hash of the keys, and if the two dictionaries have the same keys, they have the same hashes, and therefore the same order...

... Right?

Thanks!

Andy.

like image 384
Andy Avatar asked Dec 02 '22 03:12

Andy


2 Answers

No it is not guaranteed to be the same order. Imagine the scenario where you had several items in the Dictionary<TKey, TValue> with the same hash code. If they are added to the two dictionaries in different orders it will result in different orders in enumeration .

Consider for example the following (equality conforming) code

class Example
{
    public char Value;
    public override int GetHashCode()
    {
        return 1;
    }
    public override bool Equals(object obj)
    {
        return obj is Example && ((Example)obj).Value == Value;
    }
    public override string ToString()
    {
        return Value.ToString();
    }
}

class Program
{
    static void Main(string[] args)
    {
        var e1 = new Example() { Value = 'a' };
        var e2 = new Example() { Value = 'b' };
        var map1 = new Dictionary<Example, string>();
        map1.Add(e1, "1");
        map1.Add(e2, "2");

        var map2 = new Dictionary<Example, string>();
        map2.Add(e2, "2");
        map2.Add(e1, "1");

        Console.WriteLine(map1.Values.Aggregate((x, y) => x + y));
        Console.WriteLine(map2.Values.Aggregate((x, y) => x + y));
    }
}

The output of running this program is

12
21
like image 62
JaredPar Avatar answered Dec 04 '22 17:12

JaredPar


Short version: No.

Long version:

    [TestMethod]
    public void TestDictionary()
    {
        Dictionary<String, Int32> d1 = new Dictionary<string, int>();
        Dictionary<String, Int32> d2 = new Dictionary<string, int>();

        d1.Add("555", 1);
        d1.Add("abc2", 2);
        d1.Add("abc3", 3);
        d1.Remove("abc2");
        d1.Add("abc2", 2);
        d1.Add("556", 1);

        d2.Add("555", 1);
        d2.Add("556", 1);
        d2.Add("abc2", 2);
        d2.Add("abc3", 3);

        foreach (var i in d1)
        {
            Console.WriteLine(i);
        }
        Console.WriteLine();
        foreach (var i in d2)
        {
            Console.WriteLine(i);
        }
    }

Output:

[555, 1]
[abc2, 2]
[abc3, 3]
[556, 1]

[555, 1]
[556, 1]
[abc2, 2]
[abc3, 3]
like image 43
matthias.lukaszek Avatar answered Dec 04 '22 16:12

matthias.lukaszek