简体   繁体   English

C# Generics:在重写方法中显式重述继承约束可能会破坏多态性?

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

Mark Michaelis wrote in his book ( C# 4.0 Essentials ): Mark Michaelis在他的书( 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.但是,覆盖成员需要符合基本 class 方法中定义的“接口”。 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 ?有人可以向我解释break polymorphism意味着什么吗? And in this example how could polymorphism break?在这个例子中,多态性如何破坏?

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!

His example is confusing in part because of the (incorrect, IMO) re-use of T for a generic method within a generic type.他的示例令人困惑,部分原因是(不正确的,IMO)将T重用于泛型类型中的泛型方法。 The two T are not the same;两个T不一样; 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:在这里我添加了ISomethingElse - 显然第二种方法可以尝试使用第二个T的功能 - 但是,调用者可能是:

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.基本实现不强制ISomethingElse ,因此编译器不会抱怨它没有实现。 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:但是,如果您在类型级别执行此操作,它确实有效,因为具体 object 存在,我们知道约束已强制执行:

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;还有一个简短的提醒——如果你有一个带有<T>的泛型类型,不要在泛型方法中也使用<T> something more specific like TValue etc...更具体的东西,比如TValue等......

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

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