具有参数类型限制的泛型不能传递给具有非泛型参数的方法

时间:2019-10-10 13:19:59

标签: c# generics

类型差异使我的头部受伤。我的印象是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>编译正常?

1 个答案:

答案 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 { }

并通过。由于没有从FooISampleInterface的参考转换,因此不允许协方差。

如果您通过执行以下操作告诉编译器T必须另外是引用类型,则

static void GenericMethod<T>(IEnumerable<T> sequence) where T : class, ISampleInterface

然后编译器可以确定 是从TISampleInterface的引用转换,并且可以编译。