开发者

C# Generics: Explicit restate of inherited constraints in overriden methods could break polymorphism?

Mark Michaelis wrote in his book (C# 4.0 Essentials):

class EntityBase<T> where T : IComparable<T>
{
    public virtual void Method<T>(T t)
      where T : IComparable<T>
    {
        // ...
    }
}

class Entity<T> : EntityBase<T> where T : IComparable<T>
{
    public override void Method<T>(T t)
        // Error: Constraints may not be
        // repeated on overriding members
    where T : IComparable<T>
    {
        // ...
    }
}

However, overriding members need to conform to the “interface” defined in the base class method. Additional constraints could break polymorphism, so they are not allowed and the type parameter constraints on the override method are implied.

Could somebody kindly explain 开发者_运维问答to me what it means to break polymorphism? And in this example how could polymorphism break?


His example is confusing in part because of the (incorrect, IMO) re-use of T for a generic method within a generic type. The two T are not the same! So; let's work with a non-generic type:

class EntityBase
{
    public virtual void Method<T>(T t)
      where T : IComparable<T>
    {
        // ...
    }
}

class Entity : EntityBase
{
    public override void Method<T>(T t)
        // Error: Constraints may not be
        // repeated on overriding members
    where T : IComparable<T>, ISomethingElse
    {
        // ...
    }
}

Here I added ISomethingElse - and clearly the 2nd method could try to use features of this second T - however, the caller might be:

EntityBase foo = GetEntity(); // is actually an Entity (sub-type) instance
foo.Method<SomeType>();
...
EntityBase GetEntity() { return new Entity(); }

the base implementation does not enforce ISomethingElse, so the compiler does not complain that it isn't implemented. So what does the overridden method do? Hence it can't exist.

However! If you do this at the type level instead, it does work, as for the concrete object to exist we know the constraint was enforced:

class EntityBase<T> where T : IComparable<T>
{
    public virtual void Method(T t)
    {
        // ...
    }
}

class Entity<T> : EntityBase<T>
   where T : IComparable<T>, ISomethingElse
{
    public override void Method(T t)
    {
        // ... can use ISomethingElse features
    }
}

And a brief reminder - if you have a generic type with <T>, don't also use <T> in a generic method; something more specific like TValue etc...


If you were able to add additional constraints to the overridden method, it would break polymorphism.

Specifically, code that calls the base method with a parameter that doesn't meet your new constraint would break.

For example:

class Base {
    public virtual void M<T>() where T : Control { ... }
}

class Derived: Base {
    public override void M<T>() where T : Button { ... }
}


Base b = new Derived();
b.M<TextBox>();    //That's not a Button!
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜