类型差异使我的头部受伤。我的印象是out
上的IEnumerable<out T>
方差修饰符应允许这种行为。
interface ISampleInterface
{
}
/// <summary>
/// This works great!
/// </summary>
static void GenericMethod<TSeq>(TSeq sequence) where TSeq : IEnumerable<ISampleInterface>
{
UseInterface(sequence);
}
/// <summary>
/// This does not compile :(
/// </summary>
static void GenericMethod<T>(IEnumerable<T> sequence) where T : ISampleInterface
{
UseInterface(sequence);
}
static void UseInterface(IEnumerable<ISampleInterface> item)
{
throw new NotImplementedException();
}
错误是;
错误CS1503参数1:无法从
System.Collections.Generic.IEnumerable<T>
转换为System.Collections.Generic.IEnumerable<ISampleInterface>
为什么GenericMethod<T>
编译失败,但是GenericMethod<TSeq>
编译正常?
答案 0 :(得分:4)
问题在于差异(例如IEnumerable<out T>
)仅适用于引用转换。你不能做:
IEnumerable<object> x = new List<int>(); // Boxing conversion
IEnumerable<long> x = new List<int>(); // User-defined type conversion
(这很直观:使用x
的代码不知道基础集合的类型不同,因此无法将代码插入到每个int
的框中,或将每个int
转换为long
。)
在:
static void GenericMethod<T>(IEnumerable<T> sequence) where T : ISampleInterface
{
UseInterface(sequence);
}
编译器确实知道T
必须实现ISampleInterface
,但这并不能阻止您定义:
public struct Foo : ISampleInterface { }
并通过。由于没有从Foo
到ISampleInterface
的参考转换,因此不允许协方差。
如果您通过执行以下操作告诉编译器T
必须另外是引用类型,则
static void GenericMethod<T>(IEnumerable<T> sequence) where T : class, ISampleInterface
然后编译器可以确定 是从T
到ISampleInterface
的引用转换,并且可以编译。