Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generics and inheritance in C#

I have entity class generated by E-R designer that I have modified a little. 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>. 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

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

I get compile time error.

How can I add instances of BoolPref to Preferences ? Where is the mystake ?

like image 594
Rasto Avatar asked Dec 05 '22 01:12

Rasto


2 Answers

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:

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. 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.

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.

like image 89
Eric Lippert Avatar answered Dec 22 '22 14:12

Eric Lippert


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.

The good news is that with .NET 4.0, you can use covariance to get the desired effect.

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>.

like image 39
Wyatt Barnett Avatar answered Dec 22 '22 14:12

Wyatt Barnett