尽管存在通用约束,C#类型转换错误

尽管存在通用约束,C#类型转换错误,c#,generics,type-conversion,covariance,constraints,C#,Generics,Type Conversion,Covariance,Constraints,为什么在类p的类型参数T上有“必须从a继承”的泛型约束时,第一次调用成功,但第二次调用失败,并出现注释中详述的类型转换错误: abstract class A { } static class S { public static void DoFirst(A argument) { } public static void DoSecond(ICollection<A> argument) { } } static class P<T> whe

为什么在类p的类型参数T上有“必须从a继承”的泛型约束时,第一次调用成功,但第二次调用失败,并出现注释中详述的类型转换错误:

abstract class A { }

static class S
{
    public static void DoFirst(A argument) { }
    public static void DoSecond(ICollection<A> argument) { }
}

static class P<T>
    where T : A, new()
{
    static void Do()
    {
        S.DoFirst(new T());             // this call is OK

        S.DoSecond(new List<T>());      // this call won't compile with:

        /* cannot convert from 'System.Collections.Generic.List<T>'
           to 'System.Collections.Generic.ICollection<A>' */
    }
}
抽象类A{}
静态类S
{
公共静态void DoFirst(参数){}
公共静态void DoSecond(ICollection参数){}
}
静态P类
其中T:A,new()
{
静态void Do()
{
S.DoFirst(new T());//此调用正常
S.DoSecond(new List());//此调用不会使用以下命令编译:
/*无法从“System.Collections.Generic.List”转换
至“System.Collections.Generic.ICollection”*/
}
}
泛型约束是否应该确保
List
确实是
ICollection

这是C#缺少泛型类型的一个例子(C#确实支持数组协方差)。C#4将在接口类型上添加此功能,还将更新几个BCL接口类型以支持它

请参阅:

在这篇文章中,我将尝试介绍一个 C#4.0的创新。其中一个 新特性是协方差和方差 类型参数上的逆变 现在由泛型委托支持 和通用接口。首先让我们 看看这些词是什么意思:)


约束对问题没有影响;问题在于,您在需要ICollection的参数中传递列表——C#不支持协方差,因此需要将列表显式强制转换为ICollection:

S.DoSecond((ICollection<A>) new List<T>());      // this call will be happy
S.DoSecond((ICollection)new List());//这个电话会很高兴的

您已将DoSecond的参数强类型为ICollection类型。尽管T是类型A,但在编译时,List和ICollection之间没有隐式转换。调用DoSecond时,您需要创建列表并将其强制转换为ICollection,或者使DoSecond本身成为通用方法


注意:C#4.0应该支持这种类型的隐式强制转换,这将提供比C#3.0提供的更好的协方差/逆变。

问题不是IList/
ICollection
不匹配,问题是类型参数不匹配。呃,是的,T和A之间存在一个隐式的向上投射。在
IList
IList
之间没有向上投射。另外,C#4.0中的协方差支持在这里也没有帮助,因为无论是
IList
还是
ICollection
本身都是协方差的。我编辑了我的文章,以澄清我的意思。使用的类型为列表和ICollection。列表确实是一个ICollection,因为T是A的,所以ICollection应该与C#4.0中的ICollection是协变的。我为最初的不清晰道歉…希望我的编辑能让它更清晰。这在C#4.0中不会改变
IList
ICollection
不是协变的。因此,尽管C#4.0将增加对类型协方差的支持,但这种特殊情况将继续不起作用。正在使用的类型不是IList和ICollection…它们是List(具体类型,而不是接口)和ICollection。列表绝对是一个ICollection,这确实使它们具有协变性。你在三篇帖子中发表了你的评论,其中两篇显然被否决了…基于错误的类型…它不是IList,它的列表!以重复方式关闭-请参阅