繁体   English   中英

约束泛型类型参数的逆解

[英]Contravariance on constrained generic type parameters

参考在Visual Studio 2010 Express中为C#编译的这个测试代码

public class Test
{
    class Base { }
    class Derived : Base { }

    void Test1(IEnumerable<Derived> derived)
    {
        IEnumerable<Base> b = derived; //This works fine using covariance on IEnumerable
    }

    void Test2<TDerived, TBase>(TDerived derived) where TDerived : TBase
    {
        TBase b = derived; //This works fine because TDerived is constrained to derive from TBase
    }

    void Test3<TDerived, TBase>(IEnumerable<TDerived> derived) where TDerived : TBase
    {
        IEnumerable<TBase> b = derived; //ERROR: paraphrased: Cannot implicitly convert type IEnumerable<TDerived> to IEnumerable<TBase>
    }
}

我试图利用IEnumerable的协方差将一个泛型类型参数的可枚举存储在该类型参数被约束为继承的类的可枚举中。 这由Test3举例说明。 请注意,Test1和Test2(分别演示编译时类型的协方差和约束类型的赋值)都可以正常编译。 它是两种语言功能的组合,对我来说不起作用。

我能够使用IEnumerable<TBase> b = derived.Cast<TBase>()并且100%确信如果我的理解没有缺陷,任何演员都不会失败,所以我确实有一个可用的解决方法。 我的问题是,为什么编译器不允许这样做? 出于某些逻辑原因,编译器中的疏忽或其他我没有想到的其他原因,这是否被禁止?

回答最初的问题

您当前正在尝试将TDerived类型的单个元素转换为Base类型的序列 我不希望你的Cast调用工作,因为TDerived没有实现IEnumerable - 我怀疑你实际上已经TDerived在不同的情况下工作了。

我怀疑你实际上意味着:

void Test3<TDerived>(IEnumerable<TDerived> derived) where TDerived : Base
{
    IEnumerable<Base> b = derived;
}

这没有任何问题。

回答编辑过的问题

好的,现在我们在两个类型参数之间遇到了真正的问题,问题是编译器不知道它们是引用类型 - 这是泛型方差所必需的。 您可以使用TDerived上的class约束来修复它:

void Test3<TDerived, TBase>(IEnumerable<TDerived> derived)
    where TDerived : class, TBase
{
    IEnumerable<TBase> b = derived;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM