C#中的generics和inheritance
我有ER设计师生成的实体类,我修改了一下。 这是声明:
public abstract partial class Preference : EntityObject, IPreference
然后有另一个实体类声明如下:
public partial class BoolPref : Preference
所以BoolPref
inheritance自Preferences
。 现在我有了这个生成的属性:
public ObjectSet<Preference> Preferences { get { if ((_Preferences == null)) { _Preferences = base.CreateObjectSet<Preference>("Preferences"); } return _Preferences; } } private ObjectSet<Preference> _Preferences;
当我尝试将新的BoolPref添加到此ObjectSet时,如下所示
context.Preferences.AddObject(new BoolPref ());
我得到编译时错误。
如何将BoolPref的实例添加到首选项? mystake在哪里?
假设Preference
具有一个名为Value of Type T的读写属性。现在假设类型系统按照您希望的方式工作:
var set = new ObjectSet>(); set.Add(new Preference()); set.First().Value = "hello";
这在编译时是合法的,因为set.First()。Value具有编译时对象类型,而不是bool。 但是在运行时它的类型是bool, 你刚刚调用了一个setter,它接受一个bool并传递一个字符串 ,破坏了CLR中的内存,然后崩溃然后崩溃了。
这就是为什么这不合法。 在C#4中,只有在可certificate类型安全的情况下,并且仅当generics类型是接口或委托时,并且仅当变化类型参数是引用类型时,才能具有通用协方差和逆变。
简短的回答是开箱即用的generics不像“普通”对象处理多态的那样处理多态 – Preference
和Preference
是两个互不兼容的Preference
场合超类型/子类型。
好消息是,使用.NET 4.0, 您可以使用协方差来获得所需的效果。
这里的另一个问题是我不确定EF如何能够在持久性方面处理你的类,因为它可能不知道如何处理Preference
。
解决这个问题的方法是使用IPreference
接口将底层值公开为Object,这样就可以拥有一个ObjectSet
。 然后, Preference
IPreference
显式实现需要在运行时检查是否提供了与基础类型匹配的值。