vb.netdecimalseparator

Unexpected Decimal Separator Behavior with CultureInfo in .NET


In the attached images, you can observe that I am explicitly using both InvariantCulture and a new instance of CultureInfo("en-US") when converting a Double to a String:

value.ToString(Globalization.CultureInfo.InvariantCulture)
value.ToString(New Globalization.CultureInfo("en-US"))

Given these calls, the expected result should be the string "-807.7935669463161", where the decimal separator is a period (.). However, the output uses the comma (","), which matches the decimal separator of my system's regional settings.

I know how to implement a workaround, but why is the expected behavior not being respected?

If s <> value.ToString(us) Then
    Console.WriteLine($"Original value: {value}")
    Dim sFormatted As String =
        value.ToString(Globalization.CultureInfo.InvariantCulture)
    ' Should display "-807.7935669463161" :
    Console.WriteLine("sFormatted: " + sFormatted)
    ' Should display "-807.7935669463161" :
    Console.WriteLine("en-US Culture" +
             value.ToString(New Globalization.CultureInfo("en-US")))
    _usedVariables(s).Add(sFormatted)
End If

enter image description here

enter image description here

You may download the whole solution at here

****** EDIT ********* I have found what was happening. If you look at the following you will see that the last argument is a double, while the signature expects a String. But there is no error message and the code compiles and runs. So, this is because there is no Option Strict On declaration.

Dim us As New System.Globalization.CultureInfo("en-US")
Dim _usedVariables As New Dictionary(Of String, List(Of String))

Sub Main(args As String())
    Dim value As Double = 30
    Dim termValue As Double = 1.25
    Dim exponent As Double = value
    value = Math.Pow(termValue, value)
    AddToUsedVars(termValue.ToString(us) + "^" + exponent.ToString(us), -value)
End Sub

Public Sub AddToUsedVars(s As String, value As String)
    If Regex.IsMatch(s, "^\([^()]+\)") Then
        s = s.Substring(1, s.Length - 2)
    End If
    If Not _usedVariables.ContainsKey(s) Then
        _usedVariables.Add(s, New List(Of String))
    End If
    If s <> value.ToString(us) Then
        Console.WriteLine($"Original value: {value}")
        Dim sFormatted As String =
            value.ToString(Globalization.CultureInfo.InvariantCulture)
        ' Should display "-807.7935669463161" :
        Console.WriteLine("sFormatted: " + sFormatted)
        ' Should display "-807.7935669463161" :
        Console.WriteLine("en-US Culture" +
                 value.ToString(New Globalization.CultureInfo("en-US")))
        _usedVariables(s).Add(sFormatted)
    End If
End Sub

Solution

  • In the Sub AddToUsedVars you have a parameter value As String. Then you try to format it with value.ToString(<some culture info>). But this does not work, because value is already a String. It is not a Double. Change the parameter to value As Double, then your formats will work.

    During formatting, the string is not perceived as a number and therefore no numeric formats are applied to it.


    This happened because Option Strict was Off. in Visual Studio you can set the defaults for new VB projects and solutions in the menu Tools > Options: enter image description here


    For a specific project, you can set this option in the project properties, so that it applies to all project files where this option was not set explicitly: enter image description here