Ath*_*ari 6 .net c# overloading compiler-errors ambiguous
当一个方法有两个重载时,一个接受IDictionary
,另一个接受IDictionary<TKey, TValue>
,传递new Dictionary<string, int>()
给它被认为是不明确的.但是,如果两个重载被改变为接受IEnumerable
和IEnumerable<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:如果一个类同时实现这两个参数,如何接受泛型和非泛型参数而不会引起歧义?
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)