2010-10-19 58 views
3

考虑一个MyForm类,其中包含Show()的影子实现。它还包含一个CreateForm()方法,它接受的形式的一个实例,并调用阴影子:强类型泛型方法调用其参数的基类方法,而不是T中的阴影方法?

Public Class MyForm 
    Inherits Form 

    Public Shadows Sub Show() 
     MessageBox.Show("Shadowed implementation called!") 
    End Sub 
End Class 

... 

Public Sub CreateForm(ByVal childForm As MyForm) 
    childForm.MdiParent = Me 
    childForm.Show() 
    childForm.Focus() 
End Sub 

当与CreateForm(New MyForm())调用的Show()阴影实现正确调用。现在考虑下面的通用实现:

Public Sub CreateForm(Of T As Form)(ByVal childForm As T) 
    childForm.MdiParent = Me 
    childForm.Show() 
    childForm.Focus() 
End Sub 

CreateForm(Of MyForm)(New MyForm())调用,这个强类型的泛型方法从未调用阴影方法。

这是一个错误,还是我错过了什么?

回答

3

此行为是“按设计”。这里要记住的技巧是泛型方法是由自己编译和验证的(不像在C++中那样在调用者的上下文中)。因此,通用方法只知道TForm有关。它不知道MyForm,因此正确地绑定到Form上的方法。

这是正确的,因为Shadows方法只在编译时引用类型的引用使Shadow方法可见。这不是这种情况,因为编译类型的引用类型是Form(不是MyForm)。这与Overridable相反,其中行为根据运行时类型而改变。

+0

这是有道理的,但我仍然不知道如何/为什么调用者的上下文没有关系的参数类型。那不就是说像'SomeMethod(Of T)(ByVal arg As T)'这样的泛型定义总是会有一个Object类型的参数吗? – Rob 2010-10-19 20:50:18

+0

@Rob,从'arg'绑定方法的角度来看,是的,它本质上被认为是'Object'。这行在VB.Net中有点模糊,但默认情况下选项strict被禁用,并且非对象方法会发生后期绑定。 – JaredPar 2010-10-19 20:55:49

2

你错过了什么。它只知道它是在编译时处理一个表单(记住泛型不是模板!)。你可以做的唯一事情就是使用(覆盖)虚拟方法,而不是对它们进行遮蔽。

另请参阅'Shadows' vs. 'Overrides' in VB.NET有关阴影的更多信息 - 实际上并非多态。

+0

这不是说泛型定义类似于'SomeMethod (Of T)(ByVal arg As T)'总是有一个类型为'Object'的参数?我对泛型方法的调用明确指出类型为'MyForm',所以我认为编译器应该能够推断参数类型事实上,这似乎是正常的行为...? – Rob 2010-10-19 20:54:40

+0

没关系,我现在明白了:) – Rob 2010-10-19 21:17:08

1

,因为呼叫是通过仅仅基于应用到T给定类型的约束编译器静态评价这是不是一个错误,那就是Form。编译器无法预测实际类型可能包含阴影方法声明或任何未在已知父项中声明的其他方法(即Form)。

相关问题