当一个方法有两个重载时,一个接受 IDictionary
,另一个接受 IDictionary<TKey, TValue>
,将 new Dictionary<string, int>()
传递给它被认为是不明确的。但是,如果将两个重载更改为接受 IEnumerable
和 IEnumerable<KeyValuePair<TKey, TValue>>
,则调用不再有歧义。
由于Dictionary<TKey, TValue>
实现了上述所有接口(interface)(确切地说,.NET 4.5中的IDictionary<TKey, TValue>
,ICollection<KeyValuePair<TKey, TValue>>
,IDictionary
,ICollection
,IReadOnlyDictionary<TKey, TValue>
,IReadOnlyCollection<KeyValuePair<TKey, TValue>>
,IEnumerable<KeyValuePair<TKey, TValue>>
,IEnumerable
,ISerializable
,IDeserializationCallback
);由于 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/