代码示例:
interface IFoo { }
class FooImpl : IFoo { }
static void Bar<T>(IEnumerable<T> value)
where T : IFoo
{
}
static void Bar<T>(T source)
where T : IFoo
{
}
谁能解释,为什么此方法调用:
var value = new FooImpl[0];
Bar(value);
目标Bar<T>(T source)
(因此不编译)?
解决重载时,编译器是否完全考虑类型参数约束?
UPD。
为了避免与数组混淆。发生在的任何实现中IEnumerable<T>
,例如:
var value = new List<FooImpl>();
UPD 2。
@ ken2k提到了协方差。但是,让我们忘记吧FooImpl
。这:
var value = new List<IFoo>();
Bar(value);
产生相同的错误。
我敢肯定,List<IFoo>
和之间IEnumerable<IFoo>
存在隐式转换,因为我可以轻松编写如下代码:
static void SomeMethod(IEnumerable<IFoo> sequence) {}
并传递value
给它:
SomeMethod(value);
解决重载时,编译器是否完全考虑类型参数约束?
否,因为通用约束不是函数签名的一部分。您可以通过添加Bar
与常规约束相同的重载来验证这一点:
interface IBar { }
static void Bar<T>(IEnumerable<T> value)
where T : IFoo
{
}
static void Bar<T>(T source)
where T : IBar
{
// fails to compile : Type ____ already defines a member called 'Bar' with the same parameter types
}
您的代码无法编译的原因是,编译器会根据方法签名选择“最佳”匹配项,然后尝试应用通用约束。
可能不这样做的一个可能原因是,此调用会模棱两可:
{假设List<T>
有一个Add<T>(IEnumerable<T> source
)方法}
List<object> junk = new List<object>();
junk.Add(1); // OK
junk.Add("xyzzy") // OK
junk.Add(new [] {1, 2, 3, 4}); //ambiguous - do you intend to add the _array_ or the _contents_ of the array?
明显的解决方法是为采用Bar
集合的方法使用不同的名称(就像在BCL中使用Add
和一样AddRange
。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句