为什么,对于类别参数T的<!>的类型参数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>' */
    }
}

通用约束不应该确保List<T> 确实ICollection<A>吗?

有帮助吗?

解决方案

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

请参阅 C#4.0:协方差和逆变

  

在这篇文章中我<!>#8217;试着覆盖一个   C#4.0创新。其中一个   新功能是协方差和   类型参数的逆变   现在由通用代表支持   和通用接口。首先让<!>#8217; s   看看这些词是什么意思:)

其他提示

约束对问题没有影响;问题是你在一个需要ICollection的参数中传递List - C#不支持协方差,所以你需要显式地将列表转换为ICollection:

S.DoSecond((ICollection<A>) new List<T>());      // this call will be happy

您已强烈输入DoSecond参数作为类型ICollection <!> lt; A <!> gt;。尽管T是A类型的事实,但在编译时,List <!> lt; T <!> gt;之间没有隐式强制转换。和ICollection <!> lt; A <!> gt;。您将需要创建列表并将其强制转换为ICollection <!> lt; A <!> gt;当你调用DoSecond时,或者让DoSecond本身成为通用方法。

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top