2010-09-17 6 views
0

Considérez la méthode d'extension suivante:VB.NET contraintes et les sous-classes génériques

<Extension()> _ 
    Public Function Satisfies(Of T)(ByVal subject As T, ByVal specification As ISpecification(Of T)) As Boolean 
     Return specification.IsSatisfiedBy(subject) 
    End Function 

Cela fonctionne comme prévu si le sujet est la classe exacte étant exploité par le cahier des charges. Cependant, si la spécification examine la super-classe de T, cette extension ne fonctionnera pas à moins que le sujet ne soit explicitement converti en super-classe. Est-ce que je peux éviter cela? Jusqu'à présent, le meilleur que je suis en mesure de trouver est:

<Extension()> _ 
    Public Function Satisfies(Of T As Class, K As Class)(ByVal subject As T, ByVal specification As ISpecification(Of K)) As Boolean 
     Return specification.IsSatisfiedBy(TryCast(subject, K)) 
    End Function 

Mais je ne peux pas empêcher de penser qu'il ya une meilleure façon ....

Mise à jour:

Puisqu'il (apparemment) ne peut pas fonctionner comme je le souhaite dans VB.NET en raison de limitations dans le langage lui-même, est-ce que ma deuxième tentative est la plus sûre/efficace?

Répondre

4

Ceci est dû à la conception des méthodes d'extension telles qu'elles sont appliquées dans VB. Je ne sais pas pourquoi ils ont construit des extensions différemment pour VB, mais pour VB la contrainte TDerived: TBase ne peut pas exister. Malheureusement, sans cela, vous ne pouvez pas convertir TDerived en TBase et la fonction IsSatisfiedBy échoue. Pour référence:

Extension method '<methodname>' has type constraints that can never be satisfied

Votre première mise en œuvre semble être le seul qui fonctionne, ce qui est une limitation de la façon dont les méthodes d'extension sont conçus dans le cadre de VB.

+0

Merci pour la confirmation, avez mis à jour ma question dans le but d'obtenir une solution de contournement raisonnable pour cette limitation. – DanP

1

Je pensais quelque chose comme ça devrait fonctionner, mais il ne possède pas:

<Extension()> 
Public Function Satisfies(Of TBase, TDerived As TBase)(
      ByVal subject As TDerived, 
      ByVal specification As ISpecification(Of TBase)) As Boolean 
    Return specification.IsSatisfiedBy(subject) 
End Function 

Le compilateur VB dit: « méthode d'extension « Répond » est de type contraintes qui ne peut jamais être satisfait », ce qui est plutôt étrange, parce que dans C# il fonctionne:

public static class Extensions 
{ 
    public static bool Satisfies<TDerived, TBase>(
       this TDerived subject, 
       ISpecification<TBase> spec) where TDerived:TBase 
    { 
     return spec.IsSatisfiedBy(subject); 
    } 
} 

public interface ISpecification<T> 
{ 
    bool IsSatisfiedBy(T subject); 
} 

donc, la réponse semble être: utiliser C# pour cette construction, ou, comme @Dario a noté, mettre en œuvre la méthode Répond comme méthode régulière de module au lieu d'une méthode d'extension .

+1

C'est vraiment étrange, oui. Plus important encore parce que sans le '', cela fonctionne. – Dario

+0

J'ai essayé exactement la même chose ... et malheureusement, passer en C# n'est pas vraiment une option .. Je ne peux pas croire qu'il n'y a pas un moyen de le faire dans VB.NET .... – DanP

+0

@DanP Je voudrais mettez simplement l'interface ISpecification avec la méthode d'extension dans un projet séparé (C#). Vous n'avez pas besoin de changer tout votre projet, mais au moins ce scénario fonctionnerait ... En fin de compte, il s'agit de «faire avancer les choses», n'est-ce pas? – jeroenh

Questions connexes