2

I can successfully use CStr() on boxed built-in type. But how I can achieve the same with boxed custom type? I'm getting

Exception thrown:  'System.InvalidCastException' in Microsoft.VisualBasic.dll

The codez:

' sample custom type
Structure Record
    Public Property Value As Integer
    Overloads Function TOSTRING() As String  ' capitalizaition intentional to reveal usage 
        Return ">>" & Value.ToString() & "<<"
    End Function
    Shared Operator &(left As String, right As Record) As String
        Return left & right.TOSTRING()
    End Operator
    Shared Widening Operator CType(left As Record) As String
        Return left.TOSTRING()
    End Operator
End Structure

' both use cases
Sub Main()
    ' demo with built-in type
    Dim i As Integer = 3
    Dim ib As Object = i ' boxed into Object
    Debug.Print("i:" & CStr(i))
    Debug.Print("ib:" & CStr(ib)) ' works OK

    ' demo with custom type
    Dim r As New Record With {.Value = 3}
    Dim rb As Object = r ' boxed into Object
    Debug.Print("r:" & CStr(r))
    Debug.Print("rb:" & CStr(rb)) ' Exception thrown: 
                                  ' 'System.InvalidCastException' in Microsoft.VisualBasic.dll
End Sub
miroxlav
  • 11,796
  • 5
  • 58
  • 99

2 Answers2

1

You can override ToString this way:

Public Overrides Function ToString() As String
    'Put the logic here
    Return ">>" & Value.ToString() & "<<"
End

And then use Convert.ToString() method to convert the object to string.

Example:

Dim r As New Record With {.Value = 3}
Dim rb As Object = r ' boxed into Object
MessageBox.Show("rb:" & Convert.ToString(rb)) 'Shows >>3<<
Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
  • Yeah, technically correct. But will custom data types never work with `CStr()` like native types do? – miroxlav Dec 18 '15 at 05:41
  • Unfortunately I Haven't worked with `CStr` after `VB6` and I always used the `.Net` way `ToString` method. – Reza Aghaei Dec 18 '15 at 05:43
  • OK, I'm accepting this answer. Perhaps I'll mark another one in the future if someone finds how to make `CStr(rb)` working. – miroxlav Dec 18 '15 at 05:44
  • Also you can use `CStr(DirectCast(rb, Record))`. If you prefer – Reza Aghaei Dec 18 '15 at 05:52
  • Yeah, but this requires `Case` statement for expected data types. I wonder, why [tag:vb.net] handles its own boxed types seamlessly in `CStr()`? Does it use `Case` internally, too? (`Int32`, `UInt32`, `Float`. `Double`, ...). That would explain... – miroxlav Dec 18 '15 at 05:55
  • Do you have any idea about why you used `overloads` instead of `overrides`? – Reza Aghaei Dec 18 '15 at 06:01
  • I think it was part of some custom type example here at [so]. Also I think that IntelliSense offers it in some work path, perhaps when typing `Sub ToString()` (I do not remember now). – miroxlav Dec 18 '15 at 06:07
  • I think you should always use overrides for overriding base class methods. [Overloads Versus Overrides in VB.net](http://stackoverflow.com/a/7880470/3110834) – Reza Aghaei Dec 18 '15 at 06:09
  • Good. Thanks. Still wondering about that `CStr()` approach. Because [Convert.ToString() has its "features" (read: problems)](http://stackoverflow.com/questions/10355736/why-does-convert-tostringnull-return-a-different-value-if-you-cast-null). So practically results of `CStr()` would be much more "reliable" in terms of producing expected strings. – miroxlav Dec 18 '15 at 06:17
0

The best way is to override the .ToString in user types. I believe Cstr(), CBool() and many more still exist for backward compatibility. (VB6)

Another benefit of overriding .ToString in your types is that in debugging, when you watch a reference variable to your type, you have more meaningful information of the object than just the type of the object.

shadow
  • 1,883
  • 1
  • 16
  • 24