Best practice for converting an object to a string

I have seen several ways to convert Object to String in .NET, usually to display the value of an object to the user when the type of the object is unknown.

These include:

 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) 

Is there a method recommended by Microsoft, or are they all compiled to the same byte code?

EDIT:

Let me expand the question a bit:

What are the differences between these methods? I don’t see what is happening under the hood, so it would be nice to know if there is any performance advantage over others. In some cases, these calls can be made several thousand times (for example, reading from a large table) and dropping them after a couple of seconds can lead to a large UX effect.

+7
source share
3 answers

Convert.ToString(x) works gracefully, even if x is null. In general, when it comes to materials coming from the database, I think Convert is the best approach. Another suggestion, when working with floating point / decimal point, is to keep an eye on CultureInfo, i.e. Do not trust. as a decimal if you want to assume that you are using CultureInfo.InvariantCulture .

+10
source

They do different things. They compile with different MSIL code, but in most cases they are likely to have the same result.

ToString is a method defined by Object , which is an integral base type for all objects. By default, it returns the type name of the object, but can (and often) be overridden by each type so that it returns a more meaningful string. For example, in your example, x is an Int32 object, and Int32 overrides ToString , so it returns "3" instead of the standard "System.Int32".

I'm not sure, but I suspect that when you concatenate "" & x , it distinguishes x from String , in which case it is a shortcut to enter "" & CType(x, String) or "" & CStr(x) . Each type can overload the casting operator, so it assumes that the type (in this case, Int32 ) overloaded the operator and therefore can be wrapped to a string. Indeed, he has and can.

Convert.ToString does different things depending on what kind of overload you are causing. If you pass it Int32 , it will just call the object ToString() method. However, if you pass it an Object , for example, it first checks to see if the object IConvertible or IFormattable . If so, it uses one of them, otherwise the ToString method is used. Thus, he tries, depending on the type of object that you are sending it, to determine what he considers the most likely way to get this type in a string.

As far as I prefer, I would say that x.ToString() is what you want to use most often if you don't have any other problem (it all depends on what you do with the object).

+1
source

I decided to test the effectiveness of each method using a collection of 1,000,000 objects. The objects were: integer, class, Nothing, or DBNull.Value. The same collection was used for each test, and I tested each method 50 times.

"" & x
This does not actually work for all objects. It works for DBNull.Value and Nothing, but trying to use this method only with any ol object will result in an InvalidCastException. Interestingly, CStr (DBNull.Value) throws an InvalidCastException, so I'm not sure why it works.

Custom Object Results: Not Available
Results without a special object: avg 126.7 ms , median 126 ms

If(x, "").ToString()
Results with custom object: avg 140.46 ms , median 138 ms
Results without a special object: avg 69.32 ms , median 69 ms

Convert.ToString()
Results with custom object: avg 171.54 ms , median 171 ms
Results without a special object: avg 112.14 ms , median 112 ms

Thus, it seems that If(x, "").ToString() slightly faster for a very large set of records, but this should be balanced with Convert.ToString() more powerful conversion options. Thanks for answers.

Here is the code I used for testing:

 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 
+1
source

All Articles