Pepa Zdepa
Pepa Zdepa

Reputation: 91

Conversion of nullable double variable to String in VB.NET

Recently I came across a weird behaviour of a nullable double. As I need to turn a nullable variable into string with precisely set digits I am using method .ToString(format). When I apply this method on the aforementioned nullable variable instead of getting converted number as I need, I get only the first digit of this number (example is given bellow). Of course I can cast the nullable to double and it solves it, but why is it happening though. Thank you very much for your input.

Example:

'Nullable Double
Dim value As Double? = 867
Dim convertedValue As String = value.ToString("0.00000")
Console.WriteLine(convertedValue)
'Output: 8

'Not nullable Double
Dim value As Double = 867
Dim convertedValue As String = value.ToString("0.00000")
Console.WriteLine(convertedValue)
'Output: 867.00000

Upvotes: 1

Views: 921

Answers (1)

jmcilhinney
jmcilhinney

Reputation: 54457

The method you're trying to call doesn't exist. A Double? is actually a Nullable(Of Double). Any method you call on that has to be a member of the Nullable(Of T) structure. How could that type have a ToString overload that took a numeric format string as an argument when T could be a non-numeric type? Here's the documentation for the Nullable(Of T).ToString method:

https://learn.microsoft.com/en-au/dotnet/api/system.nullable-1.tostring?view=net-5.0

As you can see, there is no such overload, unlike for the Double type:

https://learn.microsoft.com/en-au/dotnet/api/system.double.tostring?view=net-5.0

If you want to use a numeric format string then you need a number and a Double? is not a number. Here's a method you can use that will format the value as a number if it is one and normally otherwise:

Private Function FormatNullableDouble(number As Double?, format As String) As String
    Return If(number.HasValue,
              number.Value.ToString(format),
              number.ToString())
End Function

You might call that like this:

Dim convertedValue As String = FormatNullableDouble(value, "0.00000")

EDIIT:

To be clear, because you have Option Strict Off, the compiler is ignoring that your code doesn't make sense and assumes that it will at run time. When run time comes around, the system tries its best to find a way to make it work. What it actually comes up with is that this:

value.ToString("0.00000")

actually means this:

value.ToString().Chars(CInt("0.00000"))

In VB, you can omit the parentheses on a method call if there are no arguments so this:

value.ToString

is equivalent to this:

value.ToString()

By assuming that you have omitted the parentheses, the system can make that ToString call make sense, so it does that.

Now it just has to do something with the format string in the parentheses. The preceding ToString call returns a String and you can index a String to get a Char value at that index, so it assumes that that is what you're trying to do. It converts your format string to an Integer and then gets the Char from the String at that index. That is why a value of 867 produces 8 as the output. You are converting the number 867 to a String, then converting the String "0.00000" to an Integer to get 0, then getting the the Char at index 0 from the String "867", which is "8"c.

All that is happening because you didn't turn Option Strict On, which tells the system to make the best guess it can to make bad code work.

Upvotes: 4

Related Questions