Reputation: 43
In C#, are the .Values and .Keys in a ImmutableSortedDictionary guaranteed to be sorted, please?
The following code:
var dict = new Dictionary<long, string>
{
{3, "Three"},
{1, "One"},
{2, "Two"}
}.ToImmutableSortedDictionary();
foreach (var p in dict)
{
System.Console.WriteLine($"{p.Key} - {p.Value}");
}
System.Console.WriteLine();
foreach (var k in dict.Keys)
{
System.Console.WriteLine(k);
}
System.Console.WriteLine();
foreach (var v in dict.Values)
{
System.Console.WriteLine(v);
}
Behaves as I was expecting, it prints all in order. Are there any guarantees that it will always do so? I checked online documentation and it does not say anything one way or the other.
Thank you.
EDIT: Neither https://learn.microsoft.com/en-us/dotnet/api/system.collections.immutable.immutablesorteddictionary-2.keys?view=netcore-3.1 nor https://learn.microsoft.com/en-us/dotnet/api/system.collections.immutable.immutablesorteddictionary-2.values?view=netcore-3.1 say one way or the other, from what I understand, the documentation only guarantees that a .GetEnumerator() on the dictionary will be sorted. So it seems that the first loop in the code above will always be sorted, but I am not sure about the second and third.
Upvotes: 0
Views: 1458
Reputation: 2062
Well, when document is not clear, source code talks (as @404 pointed out).
I agree with @mjwills. Since current documents (.NET Core 3.1) do not specify what the order of returned objects is, we cannot safely assume anything.
Keys:
Gets the keys in the immutable sorted dictionary.
Gets the values in the immutable sorted dictionary.
Method behaviors below are based on current implementation (.NET Core 3.1) of ImmutableSortedDictionary. Those behaviors are subject to change, please see conclusion aforementioned.
Keys
will return sorted resultsValues
will not return sorted resultsThat is easy to verify by running OP's code. The result for Values
is not sorted.
One
Two
Three
Reason
Both Keys
and Values
are the result of enumeration of Node which implements IEnumerable<KeyValuePair<TKey, TValue>>
.
/// <summary>
/// Gets the keys.
/// </summary>
internal IEnumerable<TKey> Keys
{
get { return Linq.Enumerable.Select(this, p => p.Key); }
}
/// <summary>
/// Gets the values.
/// </summary>
internal IEnumerable<TValue> Values
{
get { return Linq.Enumerable.Select(this, p => p.Value); }
}
Node
is an implementation of AVL tree, which adds/removes Node
always based on key (not value) comparison IComparer<TKey> keyComparer
. That is why Keys
are always sorted, while Values
are not sorted by itself.
/// <summary>
/// Adds the specified key. Callers are expected to have validated arguments.
/// </summary>
/// <param name="key">The key.</param>
/// <param name="value">The value.</param>
/// <param name="keyComparer">The key comparer.</param>
/// <param name="valueComparer">The value comparer.</param>
/// <param name="overwriteExistingValue">if <c>true</c>, an existing key=value pair will be overwritten with the new one.</param>
/// <param name="replacedExistingValue">Receives a value indicating whether an existing value was replaced.</param>
/// <param name="mutated">Receives a value indicating whether this node tree has mutated because of this operation.</param>
/// <returns>The new AVL tree.</returns>
private Node SetOrAdd(TKey key, TValue value, IComparer<TKey> keyComparer, IEqualityComparer<TValue> valueComparer, bool overwriteExistingValue, out bool replacedExistingValue, out bool mutated)
/// <summary>
/// Removes the specified key. Callers are expected to validate arguments.
/// </summary>
/// <param name="key">The key.</param>
/// <param name="keyComparer">The key comparer.</param>
/// <param name="mutated">Receives a value indicating whether this node tree has mutated because of this operation.</param>
/// <returns>The new AVL tree.</returns>
private Node RemoveRecursive(TKey key, IComparer<TKey> keyComparer, out bool mutated)
Upvotes: 2
Reputation: 6157
Seemingly it just uses a linq Select
statement to get an Enumerator for the Keys and Values as found in the implementation source. So that would garantuee all 3 statements to be sorted as one also would expect from its class name.
Upvotes: 0