SomeList <t>:List <t>不能转换为List <t>?</t> </t> </t>

时间:2011-08-03 03:04:29

标签: c# generics inheritance interface

在Main()中查看评论。为什么我不能执行以下操作?

   public class SomeList<T> : List<T>
{
    public SomeList(List<T> existing)
    {
        foreach (var item in existing)
            Add(item);
    }

    public override string ToString()
    {
        return "I'm a better list.";
    }
}

internal interface IReadStuff<T>
{
    List<T> ReadStuff();
}

public class ReaderStrategy<Foo> : IReadStuff<Foo>
{
    public List<Foo> ReadStuff()
    {
        return new List<Foo>();
    }
}

public class Foo {}

public class Main
{
    public Main()
    {
        var reader = new ReaderStrategy<Foo>();

        // This works, but type is List<Foo>, not SomeList<Foo>
        List<Foo> aList = reader.ReadStuff();
        // This does not compile, but is what I want to do:
        SomeList<Foo> aBetterList = reader.ReadStuff();
        // This compiles, but always generates null for aBetterList:
        SomeList<Foo> anotherBetterList = reader.ReadStuff() as SomeList<Foo>;
        // This is funky but works:
        SomeList<Foo> works = new SomeList<Foo>(reader.ReadStuff());
    }
}

我正在努力了解如何将泛型与继承类型一起使用。我需要上述内容,因为我希望扩展List<T>的功能是一种特殊方式,例如,请参阅SomeList<T> overrides ToString()。但是,我想使用.Net generic List<T>来保持我的工厂策略。有没有办法使这项工作?

修改

我添加了一个接受List<T>并添加到SomeList<T>的构造函数。这似乎不自然,但有效。这是一项昂贵的操作,尤其是List<T>很大的情况。

我的问题标题不是最好的,我所追求的是一个展示更好方法的例子。

4 个答案:

答案 0 :(得分:3)

reader.ReadStuff()返回List<Foo> - 但您尝试将其分配给SomeList<Foo>继承自List<Foo>的对象。这不起作用,因为List<Foo> 不是 SomeList<Foo> - 反之亦然。

考虑一下 - 从List<Foo>返回ReadStuff()对象是合法的 - 然后您尝试访问此对象上仅在SomeList<Foo>上可用的功能 - 这会破坏这就是为什么OOP不允许你这样做的原因 - 子类的实例可以在需要父类的实例的地方使用 - 但是你不能使用期望子类的父类。

返回问题标题:SomeList<T>List<T>无法转换为List<T>?是的,这是可能的,但您正在尝试将List<T>投射到SomeList<T>

答案 1 :(得分:1)

SomeList的所有实例都是List的实例。但是,并非List的所有实例都是SomeList的实例。这就是第二个任务正在做的事情。 reader.ReadStuff()返回一个List,而不是SomeList。希望这可以帮助。

答案 2 :(得分:1)

在您的示例中,您没有将SomeList<Foo>的实例投射到List<Foo>,而是试图将List<Foo>投射到SomeList<Foo>。你将从不那么具体到更具体,哪些不起作用。它应该反过来。

答案 3 :(得分:0)

更改此代码

 SomeList<Foo> aBetterList = reader.ReadStuff() 

 to 
SomeList<Foo> aBetterList = reader.ReadStuff()  as SomeList<Foo>; 

before using 
    if(aBetterList !=null) {}