You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
sortedList.DeepClone() and immutableDictionary.DeepClone() don't compile (CS0121 ambiguous between the IDictionary and IReadOnlyDictionary overloads) #86
SortedList<TKey,TValue>, ImmutableDictionary<TKey,TValue> and ImmutableSortedDictionary<TKey,TValue> each implement both IDictionary<TKey,TValue> and IReadOnlyDictionary<TKey,TValue>. DeepCloneContainerExtensions has an extension for each interface (DeepClone(this IDictionary<,>) at line 148 and DeepClone(this IReadOnlyDictionary<,>) at line 268), and neither is more specific, so calling .DeepClone() directly on these types fails to compile.
#81 (commit dad2dfc) fixed this ambiguity for ConcurrentDictionary and ReadOnlyDictionary by adding concrete overloads. The three types above still have the problem. The existing ImmutableDictionary test avoids it by cloning each value by hand instead of calling the extension, so the tests don't catch it.
error CS0121: The call is ambiguous between the following methods or properties:
'DeepCloneContainerExtensions.DeepClone<TKey, TValue>(IDictionary<TKey, TValue>)' and
'DeepCloneContainerExtensions.DeepClone<TKey, TValue>(IReadOnlyDictionary<TKey, TValue>)'
(Reproduced against the net10.0 build of current main.)
Why it matters
The README says the library clones standard collections, but a caller holding a SortedList or an immutable dictionary has to cast to one of the interfaces first. The IDictionary path then returns a plain Dictionary and loses the comparer and the sort order (tracked in #83). No cast gives back the type they started with.
SortedList<K,V> DeepClone(this SortedList<K,V>) built with new SortedList<K,V>(source.Count, source.Comparer)
ImmutableDictionary<K,V> DeepClone(this ImmutableDictionary<K,V>) built with ImmutableDictionary.CreateRange(source.KeyComparer, source.ValueComparer, clonedPairs)
ImmutableSortedDictionary<K,V> DeepClone(this ImmutableSortedDictionary<K,V>) built with source.KeyComparer and source.ValueComparer
Add tests that call .DeepClone() directly on each type (so the test fails to compile if the ambiguity comes back), and check the result type, comparer and cloned values.
What's wrong
SortedList<TKey,TValue>,ImmutableDictionary<TKey,TValue>andImmutableSortedDictionary<TKey,TValue>each implement bothIDictionary<TKey,TValue>andIReadOnlyDictionary<TKey,TValue>.DeepCloneContainerExtensionshas an extension for each interface (DeepClone(this IDictionary<,>)at line 148 andDeepClone(this IReadOnlyDictionary<,>)at line 268), and neither is more specific, so calling.DeepClone()directly on these types fails to compile.#81 (commit dad2dfc) fixed this ambiguity for
ConcurrentDictionaryandReadOnlyDictionaryby adding concrete overloads. The three types above still have the problem. The existingImmutableDictionarytest avoids it by cloning each value by hand instead of calling the extension, so the tests don't catch it.Reproduction
(Reproduced against the net10.0 build of current
main.)Why it matters
The README says the library clones standard collections, but a caller holding a
SortedListor an immutable dictionary has to cast to one of the interfaces first. TheIDictionarypath then returns a plainDictionaryand loses the comparer and the sort order (tracked in #83). No cast gives back the type they started with.Suggested fix / acceptance criteria
SortedList<K,V> DeepClone(this SortedList<K,V>)built withnew SortedList<K,V>(source.Count, source.Comparer)ImmutableDictionary<K,V> DeepClone(this ImmutableDictionary<K,V>)built withImmutableDictionary.CreateRange(source.KeyComparer, source.ValueComparer, clonedPairs)ImmutableSortedDictionary<K,V> DeepClone(this ImmutableSortedDictionary<K,V>)built withsource.KeyComparerandsource.ValueComparer.DeepClone()directly on each type (so the test fails to compile if the ambiguity comes back), and check the result type, comparer and cloned values.