2016-07-25 83 views
4

我想了解约束(类或泛型方法)如何影响方法本身。拿这个代码,例如:重写通用方法的约束

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被标记为编译器错误?

+0

案例1你有基类和dervied两个泛型 –

+0

@EhsanSajjad - 所以?在第一种情况下,它是通用类,而在第二种情况下,它是方法。没有指定一个'类约束'限制实例化只有一个?那么为什么一个人不允许,而其他人正常工作? – Madhusudhan

回答

3

让我们只考虑这个问题:“为什么是非法的虚拟覆盖约束添加到一个通用的方法是什么?”因为这非常简单。

class Foo : IComparable<Foo> { ... } 
... 
Base b = new Derived(); 
b.Method<Foo>(); 

首先,这应该是非法的吗?是。调用b.Method<Foo>实际上调用Derived.Method<Foo>,但Foo不符合限制。所以这一定是非法的。

在哪行代码应报告错误? Foo的声明是合法的。 DerivedBase的转换是合法的。从编制者的角度来看,对b.Method<Foo>的呼叫是合法的; bBaseFoo类型符合Base.Method的限制。所以这些错误不能在任何这些行上报告。唯一报告错误的地方是Base.Method中的where子句导致该问题。因此,这种where条款必须是非法的,以防止任何人编写上面其他合法的程序片段。

现在关于你的第一个案例,其中类是通用的什么?那么,如何在这种情况下获得Base<Foo>?当然不是来自Derived<Foo>的一个实例,因为你甚至不能把它放在第一位!等效的问题程序是:

Base<Foo> b = new Derived<Foo>(); 
b.Method(); 

现在应该在哪里报告错误?显然它可以在创建Derived<Foo>的行上报告!所以不需要额外的where条款是非法的。

4

在情况1中,可用于类型T的任何对象的方法中,当T是由类来确定。对于任何特定的类,只有一个类型T,因此重写很简单。你可以使用更广泛的类型吨至产生基地<牛逼>比生成派生的事实<牛逼>是没有问题的。

在情况2中,该方法可以被称为用于任何数目的类型。但是,Derived类中允许的类型只是Base类中允许的类型的一个子集,这意味着您有一个“部分重载”,这会使事情变得混乱。