SomeList<T> : List<T> can't be cast as 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) {}
精彩评论