C#中的generics和inheritance

我有ER设计师生成的实体类,我修改了一下。 这是声明:

public abstract partial class Preference : EntityObject, IPreference 

然后有另一个实体类声明如下:

 public partial class BoolPref : Preference 

所以BoolPrefinheritance自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不像“普通”对象处理多态的那样处理多态 – PreferencePreference是两个互不兼容的Preference场合超类型/子类型。

好消息是,使用.NET 4.0, 您可以使用协方差来获得所需的效果。

这里的另一个问题是我不确定EF如何能够在持久性方面处理你的类,因为它可能不知道如何处理Preference

解决这个问题的方法是使用IPreference接口将底层值公开为Object,这样就可以拥有一个ObjectSet 。 然后, Preference IPreference显式实现需要在运行时检查是否提供了与基础类型匹配的值。