重写通用方法的约束
我想了解约束(类或泛型方法)如何影响方法本身。拿这个代码,例如:重写通用方法的约束
class Base<T> where T:class, IComparable<T>
{
public virtual void Method(T obj) { }
}
class Derived<T> : Base<T> where T:class, IComparable<T>, IEnumerable<T>
{
public override void Method(T obj) { }
}
此代码编译罚款和编译器/运行时能够解析到非泛型方法“方法”这需要一个参数,它是通用型的多态调用。在基类和派生类中,类型参数的约束是不同的。
我还指定一个类约束以保持超时值类型,因为为每个值型实例中产生一个不同的类,而只有一个这样的类被实例化引用类型可能可能引起问题。
另一方面,下面的代码不能编译。
class Base
{
public virtual void Method<T>() where T : class, IComparable<T> { }
}
class Derived : Base
{
public override void Method<T>() where T : class, IComparable<T>, IEnumerable<T> { }
}
为C#语言规范指出在通用方法中的约束结转,因为它是一个压倒一切的方法,它是非法的指定任何约束作为这样。我在Google上进行了一些搜索,结果发现由于支持多态调用(关于维护方法表等)的复杂性,这是不允许的。但我仍然不明白为什么它在上面的情况1中起作用,这与此类似,只不过它是通用类。如果编译器/运行时能够在情况1中做到这一点,而情况2被标记为编译器错误?
让我们只考虑这个问题:“为什么是非法的虚拟覆盖约束添加到一个通用的方法是什么?”因为这非常简单。
class Foo : IComparable<Foo> { ... }
...
Base b = new Derived();
b.Method<Foo>();
首先,这应该是非法的吗?是。调用b.Method<Foo>
实际上调用Derived.Method<Foo>
,但Foo
不符合限制。所以这一定是非法的。
在哪行代码应报告错误? Foo
的声明是合法的。 Derived
到Base
的转换是合法的。从编制者的角度来看,对b.Method<Foo>
的呼叫是合法的; b
是Base
和Foo
类型符合Base.Method
的限制。所以这些错误不能在任何这些行上报告。唯一报告错误的地方是Base.Method
中的where
子句导致该问题。因此,这种where
条款必须是非法的,以防止任何人编写上面其他合法的程序片段。
现在关于你的第一个案例,其中类是通用的什么?那么,如何在这种情况下获得Base<Foo>
?当然不是来自Derived<Foo>
的一个实例,因为你甚至不能把它放在第一位!等效的问题程序是:
Base<Foo> b = new Derived<Foo>();
b.Method();
现在应该在哪里报告错误?显然它可以在创建Derived<Foo>
的行上报告!所以不需要额外的where
条款是非法的。
在情况1中,可用于类型T的任何对象的方法中,当T是由类来确定。对于任何特定的类,只有一个类型T,因此重写很简单。你可以使用更广泛的类型吨至产生基地<牛逼>比生成派生的事实<牛逼>是没有问题的。
在情况2中,该方法可以被称为用于任何数目的类型。但是,Derived类中允许的类型只是Base类中允许的类型的一个子集,这意味着您有一个“部分重载”,这会使事情变得混乱。
案例1你有基类和dervied两个泛型 –
@EhsanSajjad - 所以?在第一种情况下,它是通用类,而在第二种情况下,它是方法。没有指定一个'类约束'限制实例化只有一个?那么为什么一个人不允许,而其他人正常工作? – Madhusudhan