2009-07-29 7 views
7

Ce que je veux faire est, basé sur le type de T faire différentes opperations. Voici un exemple simple de mon problème.Fonction générique VB.NET

Public Shared Function Example(Of T)() As T 
    Dim retval As T 
    If TypeOf retval Is String Then 
     Dim myString As String = "Hello" 
     retval = myString 
    ElseIf TypeOf retval Is Integer Then 
     Dim myInt As Integer = 101 
     retval = myInt 
    End If 
    Return retval 
End Function 

Je reçois l'erreur « Valeur de type « String » Ne peut pas être converti en« T » Même avec la partie entière. Si je jette un objet à un objet avant de l'affecter à la révocation, cela fonctionne mais je pense que cela irait à l'encontre de mon but et serait moins efficace. Des idées? Merci!

Répondre

0

Ne retval = Ctype (myString, T) ou retVal = Ctype (MyInt, T)

6

Avec une méthode générique, T sera exactement un type à chaque fois. Disons que vous avez un code appelant Example(Of Integer). Maintenant, dans votre esprit, remplacez T par Integer. La méthode résultante contiendra ces lignes (entre autres). L'attribution d'une chaîne à un entier comme celui-ci ne fonctionnera jamais. Bien sûr, ce code ne s'exécutera jamais non plus, puisque le bloc If empêche cela, mais le code ne sera toujours pas compilé. (Du côté non, le code ci-dessus ne pourra pas être compilé car le mot-clé TypeOf est restreint à utiliser avec des types de référence, mais c'est une autre histoire)

Généralement lors de la création de méthodes génériques, vous voudrez faire la même chose avec quelle que soit la contribution que vous obtenez, mais d'une manière sûre de type. Si vous voulez avoir un comportement différent pour différents types d'entrées, il est généralement préférable de surcharger les méthodes.

+2

Vrai, mais c'est toujours possible. Tout ce qui est nécessaire est que la fonction 'cast' retourne un type générique. Le secret consiste à le projeter en premier, puis à le rejeter. Voir ma réponse ci-dessous. Fondamentalement T retval = CType (CType (YourGenericVariable, Object), T) –

1
retVal = (T) "Hello World!" 
+0

Cela ne fonctionne pas, car CType (YourGenericVariable, T) ne fonctionnera pas. –

0

Une solution alternative est encapsulent ce genre de logique dans une classe et d'utiliser la fonction VB CallByName:


    Class Aux(Of T) 
     Public Value As T 

     Private dicc As Dictionary(Of String, Object) 

     Sub New() 
      dicc = New Dictionary(Of String, Object) 
      dicc.Add("system.string", "hola") 
      dicc.Add("system.int32", 15) 
      dicc.Add("system.double", 15.0) 
     End Sub 

     Public Function Test() As T 
      Dim typeName As String = GetType(T).ToString.ToLower 

      If dicc.ContainsKey(typeName) Then 
       CallByName(Me, "Value", CallType.Set, dicc(typeName)) 
      End If 

      Return Value 
     End Function 

     Protected Overrides Sub Finalize() 
      MyBase.Finalize() 

      If Not (dicc Is Nothing) Then dicc.Clear() 
      dicc = Nothing 
     End Sub 
    End Class 
+1

Un peu d'overkill, n'est-ce pas? –

7

Il est probablement un peu tard, mais essayez ceci:

Public Shared Function CAnyType(Of T)(ByRef UTO As Object) As T 
     Return CType(UTO, T) 
    End Function 


    Public Shared Function ExecuteSQLstmtScalar(Of T)(ByVal strSQL As String) As T 
     Dim T_ReturnValue As T 

     ' Here we have the result of a DB query ' 
     Dim obj As Object = "Value from DB query cmd.ExecuteScalar" 
     Dim strReturnValue As Object = obj.ToString(); 



     Try 
      Dim tReturnType As Type = GetType(T) 

      If tReturnType Is GetType(String) Then 
       Return CAnyType(Of T)(strReturnValue) 
      ElseIf tReturnType Is GetType(Boolean) Then 
       Dim bReturnValue As Boolean = Boolean.Parse(strReturnValue) 
       Return CAnyType(Of T)(bReturnValue) 
      ElseIf tReturnType Is GetType(Integer) Then 
       Dim iReturnValue As Integer = Integer.Parse(strReturnValue) 
       Return CAnyType(Of T)(iReturnValue) 
      ElseIf tReturnType Is GetType(Long) Then 
       Dim lngReturnValue As Long = Long.Parse(strReturnValue) 
       Return CAnyType(Of T)(lngReturnValue) 
      Else 
       MsgBox("ExecuteSQLstmtScalar(Of T): This type is not yet defined.") 
      End If 

     Catch ex As Exception 

     End Try 

     Return Nothing 
    End Function 

(le secret est la projection de votre résultat générique en objet, puis la conversion de type Objet en type de modèle T).

PS:
Vous êtes responsable de vous assurer que votre code fonctionne correctement avec les types nullable et types nullables, pas ainsi que System.DbNull.Value. Par exemple lorsque la chaîne est NULL et que la valeur de retour est Boolean (non nullable). Sur une note, notez également que VB Nothing n'est pas égal à NULL, il est égal à default(T) de C# (par exemple System.Guid.Empty for Guid)

Questions connexes