I understand that, if S
is a child class of T
, then a List<S>
is not a child of List<T>
. Fine. But interfaces have a different paradigm: if Foo
implements IFoo
, then why is a List<Foo>
not (an example of) a List<IFoo>
?
As there can be no actual class IFoo
, does this mean that I would always have to cast each element of the list when exposing a List<IFoo>
? Or is this simply bad design and I have to define my own collection class ListOfIFoos
to be able to work with them? Neither seem reasonable to me...
What would be the best way of exposing such a list, given that I am trying to program to interfaces? I am currently tending towards actually storing my List<Foo>
internally as a List<IFoo>
.
Your List<Foo>
is not a subclass if List<IFoo>
because you cannot store an MyOwnFoo
object in it, which also happens to be an IFoo
implementation. (Liskov substitution principle)
The idea of storing a List<IFoo>
instead of a dedicated List<Foo>
is OK. If you need casting the list's contents to it's implementation type, this probably means your interface is not appropriate.
Here's an example of why you can't do it:
// Suppose we could do this...
public List<IDisposable> GetDisposables()
{
return new List<MemoryStream>();
}
// Then we could do this
List<IDisposable> disposables = GetDisposables();
disposables.Add(new Form());
At that point a list which was created to hold MemoryStreams now has a Form in it. Bad!
So basically, this restriction is present to maintain type safety. In C# 4 and .NET 4.0 there will be limited support for this (it's called variance) but it still won't support this particular scenario, for exactly the reasons given above.
In your returning function, you have to make the list a list of interfaces, and when you create the object, make it as an object that implements it. Like this:
function List<IFoo> getList() { List<IFoo> r = new List<IFoo>(); for(int i=0;i<100;i++) r.Add(new Foo(i+15)); return r; }
MASSIVE EDIT
You'll be able to do it with C# 4.0, but [thanks Jon]
You can get around it using ConvertAll
:
public List<IFoo> IFoos()
{
var x = new List<Foo>(); //Foo implements IFoo
/* .. */
return x.ConvertAll<IFoo>(f => f); //thanks Marc
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With