开发者

SomeList<T> : List<T> can't be cast as List<T>?

开发者 https://www.devze.com 2023-03-24 14:56 出处:网络
See comment in Main(). Why can\'t I perform the following? public class SomeList<T> : List<T>

See comment in Main(). Why can't I perform the following?

   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(开发者_StackOverflow);
}

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());
    }
}

I am struggling understanding how to use generics with inherited types. I have a need for the above because I want to extend the functionality of List<T> is some special way, for example see SomeList<T> overrides ToString(). However, I want to keep my factory strategy using .Net generic List<T>. Is there a way to make this work?

Edit

I added a constructor that accepts List<T> and adds to SomeList<T>. This doesn't seem natural, but works. This is an expensive operation, especially if List<T> is large.

My question title was not the best, what I was striving for was an example showing a better way to do this.


reader.ReadStuff() returns List<Foo> - but you are trying to assign it to an object of type SomeList<Foo> which inherits from List<Foo>. This doesn't work because List<Foo> is not a SomeList<Foo> - it's the other way round.

Think about it - it is legal to return a List<Foo> object from ReadStuff() - then you are trying to access functionality on this object that is only available on SomeList<Foo> - this will break and that's why OOP doesn't allow you to do this - instances of a child class can be used where an instance of a parent class is expected - but you cannot use a parent class where a child class is expected.

Going back to your question title: SomeList<T> : List<T> can't be cast as List<T>? Yes that's possible, but you are trying to cast List<T> to SomeList<T>.


All instances of SomeList are instances of List. However, not all instances of List are instances of SomeList. That is what the second assignment is doing. reader.ReadStuff() returns a List, not a SomeList. Hope this helps.


In your example, you're not casting an instance of SomeList<Foo> to List<Foo>, you're trying to cast a List<Foo> to a SomeList<Foo>. You're going from less specific to more specific, which doesn't work. It should work the other way around.


change this code

 SomeList<Foo> aBetterList = reader.ReadStuff() 

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

before using 
    if(aBetterList !=null) {}
0

精彩评论

暂无评论...
验证码 换一张
取 消