2010-10-19 21 views
3

Considérons une classe MyForm qui contient une implémentation masquée de Show(). Il contient également une méthode CreateForm(), qui accepte une instance de la forme et appelle le sous Ténébreux:La méthode générique fortement typée appelle la méthode de classe de base de son argument, au lieu d'une méthode ombrée dans 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 

Appelé avec CreateForm(New MyForm()), la mise en œuvre de l'ombre Show() est appelée correctement. Considérons maintenant la mise en œuvre générique suivante:

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

Appelé avec CreateForm(Of MyForm)(New MyForm()), cette méthode générique fortement typé la méthode n'invoque ombré.

Est-ce un bug ou manque-t-il quelque chose?

Répondre

3

Ce comportement est "By Design". L'astuce à retenir ici est que la méthode générique est compilée et vérifiée par elle-même (pas dans le contexte de l'appelant comme c'est le cas en C++). Par conséquent, la méthode générique sait seulement que T est liée à Form. Il n'a aucune connaissance de MyForm et donc se lie correctement aux méthodes sur Form.

Ceci est correct car les méthodes Shadows n'entrent en jeu qu'avec le type de référence au moment de la compilation, la méthode Shadow est visible. Ce n'est pas le cas ici car le type de référence au type de compilation est Form (pas MyForm)), contrairement à Overridable où le comportement change en fonction du type d'exécution

+0

Cela a du sens, mais je ne comprends toujours pas comment/pourquoi le contexte de l'appelant n'a aucune incidence sur l'argument type. Cela ne signifierait-il pas qu'un générique défini comme 'SomeMethod (OfT) (ByVal arg As T)' aurait toujours un argument de type 'Object'? – Rob

+0

@Rob, du point de vue des méthodes de liaison sur 'arg', oui, il est essentiellement considéré comme' Object'. Cette ligne est un peu floue dans VB.Net bien que, par défaut, l'option strict soit désactivée et qu'une liaison tardive se produise pour les méthodes non-Object. – JaredPar

2

Il vous manque quelque chose. Il sait seulement qu'il s'agit d'un formulaire lors de la compilation (rappelez-vous que les génériques ne sont pas des modèles!). La seule chose que vous pouvez faire est d'utiliser (override) les méthodes virtuelles au lieu de les occulter.

Voir aussi 'Shadows' vs. 'Overrides' in VB.NET pour plus d'informations sur l'ombrage - ce n'est pas vraiment un polymorphisme.

+0

Cela ne veut-il pas dire qu'un générique a été défini comme 'SomeMethod (OfV) (ByVal arg As T) 'aurait toujours un argument de type' Object'? Mon appel à la méthode générique indique explicitement le type 'MyForm', donc je pensais que le compilateur devrait être capable de déduire le type d'argument En fait, cela semble être le comportement normal ...? – Rob

+0

Nevermind, je comprends maintenant :) :) – Rob

1

Ce n'est pas un bug parce que l'appel est évalué par le compilateur statique basée uniquement sur les contraintes de type données appliquées à T, qui est Form. Le compilateur ne peut pas prédire que le type réel pourrait contenir une déclaration de méthode ombrée ou toute autre méthode non déclarée dans le parent connu (c'est-à-dire Form).