为什么我得到“类型参数必须是无效的......”错误?

时间:2011-05-26 17:38:11

标签: c# generics factory-pattern variant

我将尝试缩短此代码示例:

public interface IThing
{
    //...  Stuff
}

public class Thing1 : IThing
{  
}

public class Thing2 : IThing
{  
}

public interface IThingView<out T>
{
    ICollection<T> ViewAll();
}

public class ThingView<T> : IThingView<T>
{
    ICollection<T> ViewAll() { return new List<T>(); }  //  There's a big operation here
}

public interface IThingViewerFactory
{
    public IThingView<IThing> Build(string Which);
}

public class ThingViewerFactory
{
    public IThingView<IThing> Build(string Which)
    {
        if(Which.Equals("Thing1") { return new (IThingView<IThing>)new ThingViewer<Thing1>();}
        else { return new (IThingView<IThing>)new ThingViewer<Thing2>();}
    }
}

这是我正在做的事情的粗略概念。我有许多需要查看器的Thing类,它们将遵循comon界面。我希望一个工厂通过我传递一个带有名字的字符串来生成这些。我一直抱怨编译错误:

无效差异:类型参数“T”必须在“IThingView.ViewAll()”上无效。 'T'是协变的。

我意识到即使我开始工作,我也要做一些演员......我很好。我意识到这种方法很可能没有必要。在这一点上,这已成为一种骄傲/好奇心问题。

谢谢!

2 个答案:

答案 0 :(得分:11)

您无法创建协变ICollection<T>,因为它允许您将T放入其中。

您可以创建协变的只读集合,逆变的只写集合或不变的读写集合。
你不能同时做这两件事,或者它不是类型安全的。

答案 1 :(得分:6)

扩展SLaks答案:
要编译代码,请将ViewAll的返回类型从ICollection<T>更改为IEnumerable<T>