I am writing the base classes for a Data Model using Generics. The base classes should support:
DetailClass with DetailKey (any type)
MasterClass with MasterKey (any type) and holding a List<DetailClass>
I would like to inherit from these 2 classes, whenever I have a Master/Detail relationship in my DM.
Here is the simplified code for the base classes:
class Master<TMKey, TDKey> {
public readonly TMKey MKey;
public readonly List<Detail<TMKey, TDKey>> Details;
public Master(TMKey mKey) {
MKey = mKey;
Details = new List<Detail<TMKey, TDKey>>();
}
}
class Detail<TMKey, TDKey> {
public readonly TDKey DKey;
public readonly Master<TMKey, TDKey> Master;
public Detail(TDKey dKey, Master<TMKey, TDKey> master) {
DKey = dKey;
Master = master;
}
}
I run into troubles with the compiler, when I try to inherit from these classes:
class Sub: Detail<int, DateTime> {
public DateTime Date { get { return DKey; } }
public string S;
public Main main { get { return (Main)Master; } }
public Sub(DateTime date, string s, Main main) : base(date, main) {
S = s;
}
}
class Main: Master<int, DateTime> {
public int MainId { get { return MKey; } }
public string M;
public List<Sub> SubDetails { get { return (List<Sub>)Details; } } //compiler error
public Main(int mKey, string m) : base(mKey) {
M = m;
}
}
Compiler Error:
Cannot convert type 'System.Collections.Generic.List<FlatFileStore.Detail<int, System.DateTime>>' to 'System.Collections.Generic.List<FlatFileStore.Sub>'
It seems the compiler doesn't realise:
Sub: Detail<int, DateTime>
Any suggestion how to work around this compiler limitation ?
How needs the DM classes be changed to avoid any compiler problems and achieve high performance (i.e. no copies of collections) ?
A working sample code would be appreciated.
Edit1: It is not possible to use a .ToList() solution (see answer below). There might be thousands of details, .ToList() could get called thousands of times and each time would create a new List with thousands of items.
Edit2: The original question seemed to be a duplicate of "Casting List - covariance/contravariance problem", so I rewrote it to explain better. The other question asks specifically how to make a copy of List and therefore all answers in that question answer how to make such a copy. My question now asks how the classes have to be designed to avoid the compiler problem without using copying with its huge performance problems. There are other solutions possible, like using IReadOnlyList<T>
, which are not mentioned at all in the answers in that question. But there might be also other possibilities, like telling the Master class which Type to use for the collection it creates. Or another design might be possible. Or ...