vb.net – 当T是一个值类型时,更快的从String转换为泛型类型T的方法?

前端之家收集整理的这篇文章主要介绍了vb.net – 当T是一个值类型时,更快的从String转换为泛型类型T的方法?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
有没有人知道VB中的一种快速方式,从字符串转换为泛型类型T约束为valuetype(Of T as Structure),当我知道T将始终是某种数字类型?

这对我来说太慢了:

Return DirectCast(Convert.ChangeType(myStr,GetType(T)),T)

但它似乎是唯一一种从字符串获取的理智方法 – > T.我尝试使用Reflector来查看Convert.ChangeType是如何工作的,虽然我可以通过该代码的黑客版本从String转换为给定的数字类型,但我不知道如何将该类型转换回T所以可以退货.

我将添加我所看到的部分速度惩罚(在定时循环中)是因为返回值被分配给Nullable(Of T)值.如果我为特定的数字类型(即UInt16)强类型我的类,那么我可以大大提高性能,但是我需要为我使用的每种数字类型复制该类.

如果在通用方法/类中处理它时转换器来自T,那几乎是好的.也许存在并且我忘记了它的存在?

结论:
测试下面提供的三个实现和我原来的DirectCast / ChangeType表单,@ peenut使用预准备委托从基本类型获取Parse方法方法有效.但是,没有进行错误检查,因此实现者需要记住只使用具有Parse方法的valuetypes.或者扩展下面的内容来进行错误检查.

所有运行都在运行Windows Server 2003 R2和4GB RAM的32位系统上完成.每次“运行”是要测试的方法的1,000,000次执行(操作),使用StopWatch计时并以毫秒为单位报告.

原始DirectCast(Convert.ChangeType(myStr,T):

1000000 ops: 597ms
Average of 1000000 ops over 10 runs: 472ms
Average of 1000000 ops over 10 runs: 458ms
Average of 1000000 ops over 10 runs: 453ms
Average of 1000000 ops over 10 runs: 466ms
Average of 1000000 ops over 10 runs: 462ms

使用System.Reflection并调用InvokeMethod来获取Parse方法

1000000 ops: 12213ms
Average of 1000000 ops over 10 runs: 11468ms
Average of 1000000 ops over 10 runs: 11509ms
Average of 1000000 ops over 10 runs: 11524ms
Average of 1000000 ops over 10 runs: 11509ms
Average of 1000000 ops over 10 runs: 11490ms

Konrad生成IL代码以访问Parse方法并将调用存储到委托中的方法

1000000 ops: 352ms
Average of 1000000 ops over 10 runs: 316ms
Average of 1000000 ops over 10 runs: 315ms
Average of 1000000 ops over 10 runs: 314ms
Average of 1000000 ops over 10 runs: 314ms
Average of 1000000 ops over 10 runs: 314ms

peenut使用委托直接访问Parse方法方法

1000000 ops: 272ms
Average of 1000000 ops over 10 runs: 272ms
Average of 1000000 ops over 10 runs: 275ms
Average of 1000000 ops over 10 runs: 274ms
Average of 1000000 ops over 10 runs: 272ms
Average of 1000000 ops over 10 runs: 273ms

相比之下,peenut的方法在紧密循环中执行1,000次时快了近200ms,因此他的方法胜出.尽管如此,康拉德并不落后,而且本身就是对ILGenerator等事物的迷人研究.所有贡献者的道具!

是的,我知道更快的解决方案:-)

更快的解决方案是使用为给定(通用)类型T准备的委托.如果您只对String->(内置数字类型)感兴趣,您可以简单地使用一个参数(String)获取Parse方法.

程序测试可能性的速度.请注意,前两种方法只是通用的,第三种和第四种方法仅供比较.

Imports System.Reflection

Module Module1

    Public Class Parser(Of T As Structure)

        Delegate Function ParserFunction(ByVal value As String) As T

        Public Shared ReadOnly Parse2 As ParserFunction = GetFunction()

        Private Shared Function GetFunction() As ParserFunction
            Dim t As Type = GetType(T)
            Dim m As MethodInfo = t.GetMethod("Parse",New Type() {GetType(String)})
            Dim d As ParserFunction = DirectCast( _
               ParserFunction.CreateDelegate(GetType(ParserFunction),m),_
               ParserFunction)
            Return d
        End Function


        Public Shared Function Parse1(ByVal value As String) As T
            Return DirectCast(Convert.ChangeType(value,T)
        End Function
    End Class

    Sub Main()

        Dim w As New Stopwatch()

        'test data:
        Dim arrStr() As String = New String(12345678 - 1) {}
        Dim r As New Random
        For i As Integer = 0 To arrStr.Length - 1
            arrStr(i) = r.Next().ToString()
        Next
        Dim arrInt1() As Integer = New Integer(arrStr.Length - 1) {}
        Dim arrInt2() As Integer = New Integer(arrStr.Length - 1) {}


        Console.WriteLine("1. method - Convert.ChangeType:")
        w.Reset()
        w.Start()
        For i As Integer = 0 To arrStr.Length - 1
            arrInt1(i) = Parser(Of Integer).Parse1(arrStr(i))
        Next
        w.Stop()
        Console.WriteLine(w.Elapsed)
        Console.WriteLine()

        Console.WriteLine("2. method - prepared delegate:")
        w.Reset()
        w.Start()
        For i As Integer = 0 To arrStr.Length - 1
            arrInt2(i) = Parser(Of Integer).Parse2(arrStr(i))
        Next
        w.Stop()
        Console.WriteLine(w.Elapsed)
        Console.WriteLine()

        Console.WriteLine("3. method - Integer.Parse:")
        w.Reset()
        w.Start()
        For i As Integer = 0 To arrStr.Length - 1
            arrInt2(i) = Integer.Parse(arrStr(i))
        Next
        w.Stop()
        Console.WriteLine(w.Elapsed)
        Console.WriteLine()

        Console.WriteLine("4. method - CType:")
        w.Reset()
        w.Start()
        For i As Integer = 0 To arrStr.Length - 1
            arrInt2(i) = CType(arrStr(i),Integer)
        Next
        w.Stop()
        Console.WriteLine(w.Elapsed)
        Console.WriteLine()
    End Sub
End Module

如果需要,您可以更改已测试元素的数量.我使用了12345678个随机整数.我的计划输出

1. method - Convert.ChangeType:
00:00:03.5176071

2. method - prepared delegate:
00:00:02.9348792

3. method - Integer.Parse:
00:00:02.8427987

4. method - CType:
00:00:05.0542241

次数:3.5176071 / 2.9348792 = 1.20

猜你在找的VB相关文章