Search code examples
c#genericssubtyping

c# generic list subtype operations not working


I have a subtyped list:

public class LDBList<T> : List<T> 
    where T : LDBRootClass { ...

I need to concat them

LDBList<TSHeaderItem> catted = tsh1.Concat2(tsh2);

(and TSHeaderItem is indeed a subtype of LDBRootClass)

I get

Error CS0266 Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<LDB.TSHeaderItem>' to 'LDB.LDBList<LDB.TSHeaderItem>'. An explicit conversion exists (are you missing a cast?)

The offered cast just pushes the error from compile time to runtime.

Now I can see what's happening, ok, but I don't know how to fix it. So

  1. what do I do here specifically, and

  2. More importantly I obviously don't know enough about c# generics so to get the underlying knowledge about how to solve these class of problems, where do I start reading?

thanks!


Solution

  • Ignoring the fact that its almost never desirable to inherit from List<T>, you could create a copy constructor:

    public class LDBList<T> : List<T> where T : LDBRootClass
    {
        public LDBList(IEnumerable<T> collection) : base(collection) { }
    }
    

    Which would allow you to do this:

    var catted = new LDBList<TSHeaderItem>(tsh1.Concat2(tsh2));
    

    As for your second question, this really has nothing to do with generics but relates to the type system in general.

    tsh1.Concat2(tsh2) returns IEnumerable<TSHeaderItem>, not LDBList<TSHeaderItem>, so you need to do something to convert the IEnumerable<TSHeaderItem> into a LDBList<TSHeaderItem>.

    Although LDBList<TSHeaderItem> implements IEnumerable<TSHeaderItem>, not all IEnumerable<TSHeaderItem>s are LDBList<TSHeaderItem>s, in fact in this case the runtime type of tsh1.Concat2(tsh2) would be ConcatIterator<TSHeaderItem>.