VB.NET 泛型函数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1202549/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 14:19:10  来源:igfitidea点击:

VB.NET Generic Function

vb.netgenericsfunction

提问by Stefan Steiger

What I want to do is, based on the type of T do different opperations. Below is a simple example of my problem.

我想做的是,根据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

I get the error "Value of Type 'String' Cannot be converted to 'T'" Same with the integer part. If I cast either to an object before asigning them to retval it works but I think that would defeat my purpose and be less efficient. Any Ideas? Thanks!

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

回答by Stefan Steiger

It's probably a bit late, but try this:

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

    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

(the secrect is casting your generic result to object, then casting from type Object to template type T).

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

PS:
You are responsible to ensure that your code works correctly with nullable types and NOT nullable types, as well as System.DbNull.Value. For example when string is NULL and return value type is Boolean (not nullable). On a sidenote, please also note that VB Nothing is NOT equal NULL, it's equal to C#'s default(T)(e.g. System.Guid.Empty for Guid)

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

回答by Fredrik M?rk

With a generic method, Twill be of exactly one type each time. Let's say that you have code calling Example(Of Integer). Now, in your mind, replace Twith Integer. The resulting method will contain these lines (amongst others).

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

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

Assigning a String to an integer like that will never work. Sure, that code will also never execute, since the If-block prevents that, but the code will still not compile. (As a side not, the above code will fail to compile because the TypeOf keyword is restricted to use with reference types, but that is another story)

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

Typically when creating generic methods, you will want to do the same thing with whatever input you get, but in a type safe manner. If you want to have different behavior for different types of input, you are usually better off by overloading the methods instead.

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

回答by Spencer Ruport

retVal = (T) "Hello World!"

回答by Alejandro Díaz

An alternative solution is encapsulate this kind of logic in a class and use VB CallByName function:

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

回答by RB Davidson

Do retval = Ctype(Mystring, T) or retVal = Ctype(MyInt, T)

做 retval = Ctype(Mystring, T) 或 retVal = Ctype(MyInt, T)