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>
{
// ...
}
}
但是,压倒一切的成员需要符合中定义的"接口"基类方法。附加的约束可以打破多态性,因此它们是不允许的,并且类型替代上的参数约束方法是隐含的。
有人能向我解释一下这对break polymorphism
意味着什么吗?在这个例子中,多态性是如何打破的?
他的例子之所以令人困惑,部分原因是(不正确,IMO)在泛型类型中对泛型方法重复使用了T
。两个T
不一样!所以让我们使用一个非泛型类型:
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
{
// ...
}
}
在这里,我添加了ISomethingElse
,很明显,第二个方法可以尝试使用第二个T
的功能,但是,调用方可能是:
EntityBase foo = GetEntity(); // is actually an Entity (sub-type) instance
foo.Method<SomeType>();
...
EntityBase GetEntity() { return new Entity(); }
基本实现不强制执行ISomethingElse
,因此编译器不会抱怨它没有实现。那么被重写的方法是做什么的呢?因此它不可能存在。
然而!如果您改为在类型级别执行此操作,则确实有效,因为对于存在的具体对象,我们知道强制执行了约束:
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
}
}
还有一个简短的提醒——如果你有一个带有<T>
的泛型类型,不要在泛型方法中也使用<T>
;更具体的东西,比如TValue
等等…
如果您能够向重写的方法添加额外的约束,它将破坏多态性。
特别是,使用不满足新约束的参数调用基方法的代码会中断。
例如:
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!