如何使用泛型和继承实现Master / Detail类

时间:2017-03-28 18:39:58

标签: c# generics master-detail

我正在使用Generics编写数据模型的基类。基类应该支持: 带DetailKey的DetailClass(任何类型) MasterClass与MasterKey(任何类型)并持有List<DetailClass>

每当我的DM中有Master / Detail关系时,我想继承这两个类。

以下是基类的简化代码:

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

当我尝试从这些类继承时,我遇到了编译器的麻烦:

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

编译器错误:

Cannot convert type 'System.Collections.Generic.List<FlatFileStore.Detail<int, System.DateTime>>' to 'System.Collections.Generic.List<FlatFileStore.Sub>'

编译器似乎没有意识到:

Sub: Detail<int, DateTime>

有关如何解决此编译器限制的任何建议吗?

如何更改DM类以避免任何编译器问题并实现高性能(即没有集合副本)?

非常感谢工作示例代码。

Edit1:无法使用.ToList()解决方案(请参阅下面的答案)。可能有成千上万的细节,。ToList()可以被调用数千次,每次都会创建一个包含数千个项目的新列表。

Edit2:最初的问题似乎是“Casting List - covariance / contravariance problem”的重复,所以我重写了它以便更好地解释。另一个问题具体询问如何制作List的副本,因此该问题中的所有答案都回答了如何制作这样的副本。我现在的问题是如何设计类以避免编译器问题,而不使用其巨大的性能问题进行复制。还有其他可能的解决方案,例如使用IReadOnlyList<T>,在该问题的答案中根本没有提到。但也可能还有其他可能性,比如告诉Master类哪个Type用于它创建的集合。或者其他设计也许是可能的。或者......

1 个答案:

答案 0 :(得分:0)

这与co / contravariance有关。解决这个问题的一种方法是使用linq:

进行投射
public List<Sub> SubDetails { get { return Details.Cast<Sub>().ToList(); } } 

此处显示了其他解决方案和讨论:Casting List<T> - covariance/contravariance problem