当方法具有IDictionary和IDictionary <TKey,TValue>的重载时,模糊调用

Ath*_*ari 6 .net c# overloading compiler-errors ambiguous

当一个方法有两个重载时,一个接受IDictionary,另一个接受IDictionary<TKey, TValue>,传递new Dictionary<string, int>()给它被认为是不明确的.但是,如果两个重载被改变为接受IEnumerableIEnumerable<KeyValuePair<TKey, TValue>>,通话已经不再ambigous.

作为Dictionary<TKey, TValue>实现上述所有接口的(准确地来说IDictionary<TKey, TValue>,ICollection<KeyValuePair<TKey, TValue>>,IDictionary,ICollection,IReadOnlyDictionary<TKey, TValue>,IReadOnlyCollection<KeyValuePair<TKey, TValue>>,IEnumerable<KeyValuePair<TKey, TValue>>,IEnumerable,ISerializable,IDeserializationCallback在.NET 4.5); 由于IDictionary继承自IEnumerable并从中IDictionary<TKey, TValue>继承IEnumerable<KeyValuePair<TKey, TValue>>,我无法理解为什么会发生.

示例控制台应用:

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) {}
    }
}
Run Code Online (Sandbox Code Playgroud)

我得到的错误是:以下方法或属性之间的调用是不明确的:'​​AmbigousCall.Program.FooDic(System.Collections.IDictionary)'和'AmbigousCall.Program.FooDic(System.Collections.Generic.IDictionary)'

问题1:为什么会发生?

问题2:如果一个类同时实现这两个参数,如何接受泛型和非泛型参数而不会引起歧义?

p.s*_*w.g 7

C#将调用最具体的过载.它没有麻烦识别IEnumerable<T>更具体的比IEnumerable,因为IEnumerable<T>延伸IEnumerable.但是,IDictionary<T, U>不能延长IDictionary,所以即使Dictionary<T, U>同时实现,编译器无法识别哪些是更具体的.对于编译器,这些也可能是完全不相关的接口.

您必须使用显式强制转换为编译器提供一个提示:

FooDic((IDictionary)dic); // not ambiguous
FooDic((IDictionary<string, int>)dic); // not ambiguous
Run Code Online (Sandbox Code Playgroud)