Converting Long String of Binary to Hex C#

Does the Enumerator of a DictionaryTKey, TValue return key value pairs in the order they were added?

It's by coincidence, although predictably so. You absolutely shouldn't rely on it. Usually it will happen for simple situations, but if you start deleting elements and replacing them with anything either with the same hash code or just getting in the same bucket, that element will take the position of the original, despite having been added later than others.

It's relatively fiddly to reproduce this, but I managed to do it a while ago for another question:

using System;
using System.Collections.Generic;

class Test
{
static void Main(string[] args)
{
var dict = new Dictionary<int, int>();
dict.Add(0, 0);
dict.Add(1, 1);
dict.Add(2, 2);
dict.Remove(0);
dict.Add(10, 10);

foreach (var entry in dict)
{
Console.WriteLine(entry.Key);
}
}
}

The results show 10, 1, 2 rather than 1, 2, 10.

Note that even though it looks like the current behaviour will always yield elements in insertion order if you don't perform any deletions, there's no guarantee that future implementations will do the same... so even in the restricted case where you know you won't delete anything, please don't rely on this.

Dictionary : Will calling .Keys be ordered consistently with .Values?

Will the ordering of the keys be consistent with the ordering of the values?

Yes, it's guaranteed by the documentation of both IDictionary<,>.Keys and IDictionary<,>.Values.

Keys documentation:

The order of the keys in the Dictionary<TKey, TValue>.KeyCollection is unspecified, but it is the same order as the associated values in the Dictionary<TKey, TValue>.ValueCollection returned by the Values property.

Values documentation:

The order of the values in the Dictionary<TKey, TValue>.ValueCollection is unspecified, but it is the same order as the associated keys in the Dictionary<TKey, TValue>.KeyCollection returned by the Keys property.

Are elements in a .NET's Dictionary sequential?

The short answer is No. Order is not guaranteed in a Dictionary<TKey, TValue>, nor should you count on order being maintained.

You might want to check into OrderedDictionary instead.

Example:

OrderedDictionary d = new OrderedDictionary();

d.Add("01", "First");
d.Add("02", "Second");
d.Add("03", "Third");
d.Add("04", "Fourth");
d.Add("05", "Fifth");

for(int i = 0; i < d.Count; i++) // Print values in order
{
Console.WriteLine(d[i]);
}

Note there's no generic OrderedDictionary<TKey,TValue> version for some odd reason. However, this question has some hints on how to implement one.

ImmutableDictionary enumeration order

Because the hash function for "string" in .NET Core is non-deterministic.

The issue here depends on the key type that you're using.
If you're using string for the key type (I'm making an educated guess here that that's what you're using), in .NET Core you'll run into the issue that the hash code for the same string is different on each application execution.

You can read more about it here

In .NET Framework the same strings generated the same hash codes on each execution, so their order always remained the same during enumeration.

For your situation, you could try switching to a type where either you have a deterministic hash function either by the type itself (eg int) or supplying a type with a custom hash function.

There is a follow up question though in the original question - why is it that Dictionary<string,x> enumerates deterministically, but ImmutableDictionary<string,x> enumerates non deterministically, if both are keyed on strings, and strings generate different hashes on each application execution.

The answer here is how the enumerator works for each type. For the Dictionary<TKey,TValue> in Core, there are essentially two collections, the hashes, and the entries (see the diagrams in this article). The enumeration of Dictionary uses the entries, and by and large the entries appear in the order they were added, so it has nothing to do with the hashing function. The enumerator code you can see in the custom enumerator of KeyCollection of Dictionary here.

However for the ImmutableDictionary, the enumeration follows the hashes (see the HashBucket.Enumerator that is called in the ImmutableDictionary). So in Framework, where strings hashed consistently, everything was fine, the hashes retained their order. Now in Core though, using a string key, the hashes are different on each run, they evaluate to different positions, their order is hence different.

Hope that covers it.

The order of elements in Dictionary

The order of elements in a dictionary is non-deterministic. The notion of order simply is not defined for hashtables. So don't rely on enumerating in the same order as elements were added to the dictionary. That's not guaranteed.

Quote from the doc:

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

When SortedDictionary is enumerated does it return KeyValuePairs in expected order?

Yes definitely, although you are going to find it very hard to find documentation that clarifies this precisely.

Although the documentation for each of the four GetEnumerator overloads on this type make vague statements about returning "an enumerator that iterates through a collection", it is obvious enough that they should produce equivalent (sorted by key) sequences; remember that a sorted-dictionary is meant to "represent a collection of key/value pairs that are sorted on the key." It would be highly unintuitive and confusing for users if a collection behaved completely differently (i.e. with a different enumeration order) between a foreach loop and a LINQ to Objects query, for example.

The best I can do is provide you with the implementations of the two GetEnumerator methods you appear to be interested in (as of .NET 4.0). They are identical - they return an instance of the nested Enumerator type, with the same arguments for its constructor. The only difference is the boxing of the struct-type in the second overload:

// Used when you do foreach(var kvp in dict) { ... }

public Enumerator<TKey, TValue> GetEnumerator()
{
return new Enumerator<TKey, TValue>
((SortedDictionary<TKey, TValue>) this, 1);
}

// Used when you do:
// foreach(var kvp in (ICollection<KeyValuePair<TKey, TValue>>)dict) { ... }
// or use LINQ to Objects on the collection.

IEnumerator<KeyValuePair<TKey, TValue>>
IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()
{
return new Enumerator<TKey, TValue>
((SortedDictionary<TKey, TValue>) this, 1);
}

In fact, the only GetEnumerator overload that has a slightly different implementation is the IDictionary.GetEnumerator method. This changes an argument to the constructor-call such that the resulting enumerator produces DictionaryEntry instances rather than KeyValuePair<,> instances. Of course, the enumeration order will still be the same as with the other overloads.



Related Topics



Leave a reply



Submit