【问题标题】:VB.NET Generic FunctionVB.NET 通用函数
【发布时间】:2009-07-29 19:37:32
【问题描述】:

我想做的是,根据 T 的类型做不同的操作。下面是我的问题的一个简单示例。

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

我收到错误“'String'类型的值无法转换为'T'”与整数部分相同。如果我在将它们分配给 retval 之前将它们转换为一个对象,它会起作用,但我认为这会破坏我的目的并且效率会降低。有任何想法吗?谢谢!

【问题讨论】:

    标签: vb.net generics function


    【解决方案1】:

    可能有点晚了,但试试这个:

        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
    

    (秘密是将您的通用结果转换为对象,然后从类型对象转换为模板类型 T)。

    PS:
    您有责任确保您的代码与可空类型和不可空类型以及 System.DbNull.Value 一起正常工作。例如,当字符串为 NULL 且返回值类型为布尔值(不可为空)时。另外请注意,VB Nothing 不等于 NULL,它等于 C# 的 default(T)(例如,System.Guid.Empty for Guid)

    【讨论】:

      【解决方案2】:

      使用泛型方法,T 每次都将是一种类型。假设您有代码调用Example(Of Integer)。现在,在您的脑海中,将T 替换为Integer。生成的方法将包含这些行(以及其他行)。

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

      像这样将字符串分配给整数是行不通的。当然,该代码也永远不会执行,因为 If 块阻止了这种情况,但代码仍然无法编译。 (另一方面,上面的代码将无法编译,因为 TypeOf 关键字被限制为与引用类型一起使用,但这是另一回事)

      通常在创建泛型方法时,您会希望对所获得的任何输入执行相同的操作,但要以类型安全的方式进行。如果你想对不同类型的输入有不同的行为,你通常最好重载方法。

      【讨论】:

      • 是的,但仍有可能。所需要的只是“cast”函数返回一个泛型类型。秘诀是先将其转换为对象,然后再转换回去。请看下面我的回答。基本上 T retval = CType(CType(YourGenericVariable, Object), T)
      【解决方案3】:
      retVal = (T) "Hello World!"
      

      【讨论】:

      • 这不起作用,因为 CType(YourGenericVariable, T) 不起作用。
      【解决方案4】:

      执行 retval = Ctype(Mystring, T) 或 retVal = Ctype(MyInt, T)

      【讨论】:

        【解决方案5】:

        另一种解决方案是将这种逻辑封装在一个类中并使用 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
        

        【讨论】:

        • 有点矫枉过正,不是吗?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-13
        • 2010-10-28
        • 2012-12-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多