Reputation: 91
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
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