简体   繁体   English

C#中的泛型和继承

[英]Generics and inheritance in C#

I have entity class generated by ER designer that I have modified a little. 我有ER设计师生成的实体类,我修改了一下。 This is declaration: 这是声明:

public abstract partial class Preference<T> : EntityObject, IPreference<T>

Then there is another entity class declared as follows: 然后有另一个实体类声明如下:

public partial class BoolPref : Preference<bool>

so BoolPref inherits from Preferences<bool> . 所以BoolPref继承自Preferences<bool> Now I have this generated property: 现在我有了这个生成的属性:

public ObjectSet<Preference<object>> Preferences
    {
        get
        {
            if ((_Preferences == null))
            {
                _Preferences = base.CreateObjectSet<Preference<object>>("Preferences");
            }
            return _Preferences;
        }
    }
    private ObjectSet<Preference<object>> _Preferences;

When I try to add new BoolPref to this ObjectSet as follows 当我尝试将新的BoolPref添加到此ObjectSet时,如下所示

context.Preferences.AddObject(new BoolPref ());

I get compile time error. 我得到编译时错误。

How can I add instances of BoolPref to Preferences ? 如何将BoolPref的实例添加到Preferences? Where is the mystake ? mystake在哪里?

Suppose Preference<T> has a read-write property called Value of type T. Now suppose the type system works the way you'd like it to: 假设Preference<T>具有一个名为Value of Type T的读写属性。现在假设类型系统按照您希望的方式工作:

var set = new ObjectSet<Preference<object>>();
set.Add(new Preference<bool>());
set.First().Value = "hello"; 

That's legal at compile time because set.First().Value has compile time type of object, not bool. 这在编译时是合法的,因为set.First()。Value具有编译时对象类型,而不是bool。 But at runtime it is of type bool, and you just called a setter that takes a bool and passed a string , corrupting memory in the CLR which then crashes and dies horribly. 但是在运行时它的类型为bool, 你只需要调用一个带有bool并传递一个字符串的setter ,破坏CLR中的内存然后崩溃并死得很厉害。

That's why this is not legal. 这就是为什么这不合法。 In C# 4 you can have generic covariance and contravariance only if it is provably typesafe, and only if the generic type is an interface or delegate, and only if the varying type argument is of reference type. 在C#4中,只有在可证明类型安全的情况下,并且仅当泛型类型是接口或委托时,并且仅当变化类型参数是引用类型时,才能具有通用协方差和逆变。

The short answer is that generics, out of the box, don't handle polymorphism in the same way which "normal" objects handle polymorphism-- Preference<object> and Preference<bool> are two mutually incompatible occasions of Preference<T> not a supertype/subtype. 简短的回答是,开箱即用的泛型不会以“普通”对象处理多态的方式处理多态性 - Preference<object>Preference<bool>是两个互不兼容的Preference<T>场合超类型/子类型。

The good news is that with .NET 4.0, you can use covariance to get the desired effect. 好消息是,使用.NET 4.0, 您可以使用协方差来获得所需的效果。

The other issue here is I'm not sure how the EF is going to be able to handle your class in terms of persistence as it probably has no idea what to do with Preference<T> . 这里的另一个问题是我不确定EF如何能够在持久性方面处理你的类,因为它可能不知道如何处理Preference<T>

The way around this is to have an IPreference interface that exposes the underlying value as an Object, so you can have an ObjectSet<IPreference> . 解决这个问题的方法是使用IPreference接口将底层值公开为Object,这样就可以拥有一个ObjectSet<IPreference> The Preference<T> explicit implementation of IPreference would then need to check at runtime whether it is being provided values that match the underlying type. 然后, Preference<T> IPreference显式实现需要在运行时检查是否提供了与基础类型匹配的值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM