2009-07-29 30 views
7

Lo que quiero hacer es, en función del tipo de T hacer diferentes operaciones. A continuación se muestra un ejemplo simple de mi problema.VB.NET Función genérica

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 

me sale el error "valor de tipo 'cadena' no se puede convertir a 'T'" Lo mismo pasa con la parte entera. Si lanzo a un objeto antes de asignarlos a retval funciona, pero creo que eso vencería mi propósito y sería menos eficiente. ¿Algunas ideas? ¡Gracias!

Respuesta

0

No retval = Ctype (mystring, T) o RetVal = Ctype (Myint, T)

6

Con un método genérico, T habrá de exactamente un tipo cada vez. Supongamos que tiene un código que llama al Example(Of Integer). Ahora, en su mente, reemplace T con Integer. El método resultante contendrá estas líneas (entre otras).

Dim retval As Integer 
    If TypeOf retval Is String Then 
     Dim myString As String = "Hello" 
     retval = myString 
' more code follows ' 

Asignar una cadena a un número entero como ese nunca funcionará. Claro, ese código tampoco se ejecutará nunca, ya que el bloque If lo impide, pero el código aún no se compilará. (Como un lado no, el código anterior no se compilará porque la palabra clave TypeOf está restringida para usar con tipos de referencia, pero esa es otra historia)

Normalmente, al crear métodos genéricos, debe hacer lo mismo con cualquiera sea la información que reciba, pero de una manera segura. Si desea tener un comportamiento diferente para los diferentes tipos de entrada, por lo general, es mejor sobrecargar los métodos en su lugar.

+2

Es cierto, pero aún es posible. Todo lo que es necesario es que la función 'moldear' devuelva un tipo genérico. El secreto es arrojarlo para objetar primero, y luego devolverlo. Ver mi respuesta a continuación. Básicamente T retval = CType (CType (YourGenericVariable, Object), T) –

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

Esto no funciona, porque CType (YourGenericVariable, T) no funcionará. –

0

Una solución alternativa es encapsular este tipo de lógica en una clase y utilizar la función de 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 poco exagerado, ¿no? –

7

Es probable que sea un poco tarde, pero intente esto:

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 

(el secreto está arrojando su resultado genérico a objeto, luego lanzando de tipo Objeto a plantilla tipo T).

PS:
usted es responsable de asegurarse de que su código funciona correctamente con los tipos anulables y tipo no anulables, así como System.DbNull.Value. Por ejemplo, cuando string es NULL y el tipo de valor de retorno es Boolean (no anulable). En una nota al margen, tenga en cuenta que VB Nothing NO es igual a NULL, es igual a C# default(T) (por ejemplo, System.Guid.Empty for Guid)

Cuestiones relacionadas