7

Object.NET で anを aに変換する多くの方法を見てきましたString。通常は、オブジェクトの型が不明な場合にオブジェクトの値をユーザーに表示するためのものです。

これらには以下が含まれます:

Dim x as Object = 3
Dim y as Object = Nothing
Dim z as Object = DBNull.Value
Dim l_displayString As String

l_displayString = "" & x & "" & y & "" & z
l_displayString = If(x, "").ToString() & If(y, "").ToString() & If(z, "").ToString()
l_displayString = Convert.ToString(x) & Convert.ToString(y) & Convert.ToString(z)

Microsoft が推奨する方法はありますか、それともこれらはすべて同じバイト コードにコンパイルされますか?

編集:

質問を少し拡張して、以下を含めます。

これらの方法の違いは何ですか? ボンネットの下で何が起こっているのかはわかりません。そのため、他のものよりもパフォーマンス上の利点があるかどうかを知っておくとよいでしょう. 場合によっては、これらの呼び出しが数千回行われる場合があり (大きなテーブルからの読み取りなど)、数秒短縮することで UX に大きな影響を与える可能性があります。

4

3 に答える 3

12

x が nullの Convert.ToString(x)場合でも、 は正常に動作します。一般に、データベースからのものを扱う場合、Convert が最良のアプローチだと思います。別の提案として、浮動小数点数/10 進数を使用する場合は、CultureInfo に注意してください。つまり、. を使用することを想定したい場合は、小数点としてCultureInfo.InvariantCulture.

于 2012-07-05T15:49:44.483 に答える
1

1,000,000 個のオブジェクトのコレクションを使用して、各メソッドのパフォーマンスをテストすることにしました。オブジェクトは、整数、クラス、Nothing、または DBNull.Value のいずれかでした。各テストには同じコレクションが使用され、各メソッドを 50 回テストしました。

"" & x
これは実際にはすべてのオブジェクトで機能するわけではありません。DBNull.Value および Nothing に対しては機能しますが、このメソッドを古いオブジェクトだけで使用しようとすると、InvalidCastException が発生します。興味深いことに、CStr(DBNull.Value) は InvalidCastException をスローするため、なぜ機能するのかわかりません。

カスタム オブジェクトを使用した結果:該当なし
カスタム オブジェクトを使用しない 結果: 平均126.7 ミリ秒、中央値126 ミリ秒

If(x, "").ToString()
カスタム オブジェクトを使用した結果: 平均140.46 ミリ秒、中央値138 ミリ秒
カスタム オブジェクトを使用しない 結果: 平均69.32 ミリ秒、中央値69 ミリ秒

Convert.ToString()
カスタム オブジェクトを使用した結果: 平均171.54 ミリ秒、中央値171 ミリ秒
カスタム オブジェクトを使用しない 結果: 平均112.14 ミリ秒、中央値112 ミリ秒

If(x, "").ToString()そのため、非常に大きなレコードのセットでは少し高速に見えますが、Convert.ToString()のより強力な変換オプションとのバランスを取る必要があります。答えてくれてありがとう。

テストに使用したコードは次のとおりです。

Option Strict Off

Module Module1

    Sub Main()
        Dim l_objectArray = Enumerable.Range(0, 1000000).Select(Function(x) GetObject(x)).ToArray()

        Dim l_stopWatch As New Stopwatch()
        Dim l_testResults As New List(Of Long)
        Dim l_testIterations As Integer = 50
        Dim l_displayValue As String

        Do

            ' --------------------

            'Console.WriteLine()
            'Console.WriteLine("Conversion using string concatenation")
            'l_testResults.Clear()

            'For iteration = 0 To l_testIterations - 1
            '    l_stopWatch.Start()
            '    For Each o In l_objectArray
            '        l_displayValue = "" & o
            '    Next
            '    l_stopWatch.Stop()
            '    l_testResults.Add(l_stopWatch.ElapsedMilliseconds)
            '    l_stopWatch.Reset()
            'Next

            'Console.WriteLine()
            'Console.WriteLine("Average: " & l_testResults.Average())
            'Console.WriteLine("Median: " & GetMedian(l_testResults.ToArray()))

            ' --------------------

            Console.WriteLine()
            Console.WriteLine("Conversion using Object.ToString()")
            l_testResults.Clear()

            For iteration = 0 To l_testIterations - 1
                l_stopWatch.Start()
                For Each o In l_objectArray
                    l_displayValue = If(o, "").ToString()
                Next
                l_stopWatch.Stop()
                l_testResults.Add(l_stopWatch.ElapsedMilliseconds)
                l_stopWatch.Reset()
            Next

            Console.WriteLine()
            Console.WriteLine("Average: " & l_testResults.Average())
            Console.WriteLine("Median: " & GetMedian(l_testResults.ToArray()))

            ' --------------------

            Console.WriteLine()
            Console.WriteLine("Conversion using Convert.ToString(x)")
            l_testResults.Clear()

            For iteration = 0 To l_testIterations - 1
                l_stopWatch.Start()
                For Each o In l_objectArray
                    l_displayValue = Convert.ToString(o)
                Next
                l_stopWatch.Stop()
                l_testResults.Add(l_stopWatch.ElapsedMilliseconds)
                l_stopWatch.Reset()
            Next

            Console.WriteLine()
            Console.WriteLine("Average: " & l_testResults.Average())
            Console.WriteLine("Median: " & GetMedian(l_testResults.ToArray()))

            ' --------------------

            Console.WriteLine()
            Console.Write("Exit? (y/n): ")
            Dim l_key = Console.ReadKey(False)
            If l_key.Key = ConsoleKey.Y Then
                Exit Sub
            End If

        Loop

    End Sub

    Private Function GetMedian(ByVal values As Long()) As Long
        Array.Sort(values)
        If values.Length Mod 2 = 0 Then
            Return (values(values.Length / 2) + values(values.Length / 2 - 1)) / 2
        Else
            Return values(CInt(Math.Floor(values.Length / 2)))
        End If
    End Function

    Private Function GetObject(ByVal someNumber As Integer) As Object
        Select Case someNumber Mod 4
            Case 0
                Return someNumber
            Case 1
                Return New SomeClass(someNumber)
                'Return Nothing
            Case 2
                Return DBNull.Value
            Case Else
                Return Nothing
        End Select
    End Function

    Private Class SomeClass

        Private _seed As Integer

        Public Sub New(ByVal seed As Integer)
            _seed = seed
        End Sub

        Public Overrides Function ToString() As String
            Return _seed.ToString()
        End Function

    End Class

End Module
于 2012-07-05T17:23:05.103 に答える
1

彼らはさまざまなことをします。それらは異なる MSIL コードにコンパイルされますが、ほとんどの場合、おそらく同じ結果になります。

ToStringObjectは、すべてのオブジェクトの固有の基本型であるによって定義されるメソッドです。デフォルトでは、オブジェクトの型名を返しますが、より意味のある文字列を返すように、型ごとにオーバーライドできます (多くの場合、オーバーライドされます)。たとえば、あなたの例でxは、Int32オブジェクトであり、Int32オーバーライドするため、デフォルトの「System.Int32」の代わりにToString返されます。"3"

私は肯定的ではありませんが、連結を行うと、"" & xにキャストxされているのではないかと思います。この場合、 orStringを入力するためのショートカットです。各型はキャスト演算子をオーバーロードできるため、型 (この場合は ) が演算子をオーバーロードしたため、文字列にキャストできると想定されます。確かにそれは持っているし、できる。"" & CType(x, String)"" & CStr(x)Int32

Convert.ToString呼び出すオーバーロードに応じて、さまざまなことを行います。を渡すとInt32、オブジェクトのToString()メソッドが呼び出されます。ただし、Objectたとえば を渡すと、オブジェクトがIConvertibleorを実装しているかどうかが最初にチェックされますIFormattable。存在する場合はそれらのいずれかを使用し、そうでない場合はそのToStringメソッドを使用します。そのため、送信されたオブジェクトのタイプに応じて、そのタイプを文字列に取得するための最も可能性の高い方法を判断しようとします。

優先される方法については、x.ToString()他の懸念がない限り、常に使用したい方法です (オブジェクトで何をしているかによって異なります)。

于 2012-07-05T16:00:28.147 に答える