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

馋奶兔 提交于 2020-01-05 07:51:09

问题


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?


回答1:


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




回答2:


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!


来源:https://stackoverflow.com/questions/6242823/c-sharp-generics-explicit-restate-of-inherited-constraints-in-overriden-methods

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!