【发布时间】:2017-03-28 18:39:57
【问题描述】:
我正在使用泛型为数据模型编写基类。基类应支持:
带有 DetailKey 的 DetailClass(任何类型)
MasterClass 与 MasterKey(任何类型)并持有 List<DetailClass>
每当我的 DM 中有主/从关系时,我想从这 2 个类继承。
这是基类的简化代码:
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 用于它创建的集合。或者另一种设计可能是可能的。或者...
【问题讨论】:
-
做自己想做的事既不可能也不安全。基类属性类型允许将
Detail<int, DateTime>的any 实例添加到列表中,因此您不能保证列表仅包含Sub值。如果你想要一个简单的演员表工作,你需要两件事:1) 派生类必须是创建列表的那个,2) 你需要使用IReadOnlyList<T>而不是基类属性类型中的List<T>,例如你可以分配IReadOnlyList<Detail<int, DateTime>> Details = new List<Sub>; -
@PeterDuniho:您的评论帮助我更好地理解问题并调查可能的解决方案。我将尝试按照您的建议提出一些代码,除非您想以正确的答案提供代码。我希望您可以删除“标记为重复”。甚至您自己的评论也证明我的问题是不同的。正确设计 Master/Detail 类有很多挑战,我相信其他人会很高兴在这里找到该代码。另一个问题根本没有帮助。
-
“我重写了它以便更好地解释”——你应该小心那个编辑功能。编辑一个问题来改进它很好,但是一旦其他用户回答了您的问题,您就不能改变问题的基本性质(正如您在此处所做的那样)。发布一个新问题,在其中详细描述您迄今为止所学的内容(例如,试试我的建议),以及您仍在尝试解决的具体问题,这是一种更好的方法.我建议这样做。然后是其他用户可以解决的一个新的、可回答的问题。
-
我同意不应从根本上改变问题。但我觉得“有什么建议可以解决这个编译器限制吗?” 和 “需要如何更改 DM 类以避免任何编译器问题并实现高性能(即没有集合的副本) ?” 仍然要求他们同样的事情。请注意,Stackoverflow 明确要求我 “如果这个问题不同,请编辑它以解释它有何不同。” 我做了。我希望您现在可以删除 “由 Peter Duniho 标记为重复”。它可能会阻止其他人阅读此问题。
-
"which I did" -- 我承认它可以解释,但我的观点是您的编辑改变了问题,而不是解释了原始问题的不同之处。如果您愿意发布一个新问题,我很乐意为您提供答案,但从网站审核的角度来看,我认为上述问题应该保持关闭。在您的新问题中,请从头开始撰写(不是从这里复制/粘贴),提供我在my previous comment 中描述的详细信息
标签: c# generics master-detail