Ambiguous call when a method has overloads for IDictionary and IDictionary<TKey, TValue>
.net, ambiguous, c#, compiler-errors, overloading
Solution
C# will call the most specific overload available. It has no trouble identifying `IEnumerable<T>` as more specific than `IEnumerable` because `IEnumerable<T>` extends `IEnumerable`. However, `IDictionary<T, U>` does not extend `IDictionary`, so even though `Dictionary<T, U>` implements both, the compiler cannot identify which is more specific. To the compiler, these might as well be completely unrelated interfaces.
You'd have to give the compiler a hint by using an explicit cast:
FooDic((IDictionary)dic); // not ambiguous
FooDic((IDictionary<string, int>)dic); // not ambiguous
Problem
When a method has two overloads, one accepting `IDictionary` and another accepting `IDictionary<TKey, TValue>`, passing `new Dictionary<string, int>()` to it is considered ambigous. However, if the two overloads are changed to accept `IEnumerable` and `IEnumerable<KeyValuePair<TKey, TValue>>`, the call is no longer ambigous. As `Dictionary<TKey, TValue>` implements all of the above interfaces (to be precise, `IDictionary<TKey, TValue>`, `ICollection<KeyValuePair<TKey, TValue>>`, `IDictionary`, `ICollection`, `IReadOnlyDictionary<TKey, TValue>`, `IReadOnlyCollection<KeyValuePair<TKey, TValue>>`, `IEnumerable<KeyValuePair<TKey, TValue>>`, `IEnumerable`, `ISerializable`, `IDeserializationCallback` in .NET 4.5); as `IDictionary` is inherited from `IEnumerable` and `IDictionary<TKey, TValue>` is inherited from `IEnumerable<KeyValuePair<TKey, TValue>>`, I can't understand why it happens. Sample console application: ``` using System; using System.Collections; using System.Collections.Generic; namespace AmbigousCall { internal class Program { static void Main (string[] args) { var dic = new Dictionary<string, int>(); FooDic(dic); // Error: The call is ambiguous FooEnum(dic); // OK: The generic method is called Console.ReadKey(); } static void FooDic (IDictionary dic) {} static void FooDic<TKey, TValue> (IDictionary<TKey, TValue> dic) {} static void FooEnum (IEnumerable dic) {} static void FooEnum<TKey, TValue> (IEnumerable<KeyValuePair<TKey, TValue>> dic) {} } } ``` The error I get is: The call is ambiguous between the following methods or properties: 'AmbigousCall.Program.FooDic(System.Collections.IDictionary)' and 'AmbigousCall.Program.FooDic(System.Collections.Generic.IDictionary)' Question 1: Why does it happen? Question 2: How to accept both generic and non-generic arguments without causing ambiguity if a class implements both?