当一个方法有两个重载时,一个接受 IDictionary ,另一个接受 IDictionary<TKey, TValue> ,将 new Dictionary<string, int>() 传递给它被认为是不明确的。但是,如果将两个重载更改为接受 IEnumerableIEnumerable<KeyValuePair<TKey, TValue>> ,则调用不再有歧义。

由于Dictionary<TKey, TValue>实现了上述所有接口(interface)(确切地说,.NET 4.5中的IDictionary<TKey, TValue>ICollection<KeyValuePair<TKey, TValue>>IDictionaryICollectionIReadOnlyDictionary<TKey, TValue>IReadOnlyCollection<KeyValuePair<TKey, TValue>>IEnumerable<KeyValuePair<TKey, TValue>>IEnumerableISerializableIDeserializationCallback);由于 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) {}
    }
}

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

问题一:为什么会这样?

问题2:如果一个类同时实现了泛型和非泛型参数,又如何避免产生歧义,该如何接受呢?

最佳答案

C# 将调用最具体的可用重载。将 IEnumerable<T> 识别为比 IEnumerable 更具体没有问题,因为 IEnumerable<T> 扩展了 IEnumerable 。但是, IDictionary<T, U> 没有扩展 IDictionary ,因此即使 Dictionary<T, U> 实现了两者,编译器也无法识别哪个更具体。对于编译器来说,这些也可能是完全不相关的接口(interface)。

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

FooDic((IDictionary)dic); // not ambiguous
FooDic((IDictionary<string, int>)dic); // not ambiguous

关于c# - 当方法具有 IDictionary 和 IDictionary<TKey, TValue> 重载时的不明确调用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/16197715/

10-11 18:19