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?