11

I have code that was originally written for an English language market where the decimal separator is "." so it's expecting numeric values as strings to use "." as the separator. But we now have users in other places, e.g., places in Europe where the decimal separator is ",".

So, in the context of my software (really just the current thread) I want to override the decimal separator for the current language to be "." even if it defaults to something else.

I tried

  String sep = "."; 
  NumberFormatInfo nfi1 = NumberFormatInfo.CurrentInfo;
  nfi1.NumberDecimalSeparator = sep;

But I get an "Instance is read-only" exception on the third line. Apparently NumberFormatInfo is not writable. So how DO you set the current language's decimal separator to something other than its default?

user316117
  • 7,971
  • 20
  • 83
  • 158
  • You need to set `Thread.CurrentCulture` to a **new** instance of `CultureInfo` and make changes to that instance. – Michael Liu Jul 16 '14 at 16:16

2 Answers2

29

You need to create a new culture and you can use the current culture as a template and only change the separator. Then you must set the current culture to your newly created one as you cannot change the property within current culture directly.

string CultureName = Thread.CurrentThread.CurrentCulture.Name;
CultureInfo ci = new CultureInfo(CultureName);
if (ci.NumberFormat.NumberDecimalSeparator != ".")
{
    // Forcing use of decimal separator for numerical values
    ci.NumberFormat.NumberDecimalSeparator = ".";
    Thread.CurrentThread.CurrentCulture = ci;
 }
CathalMF
  • 9,705
  • 6
  • 70
  • 106
  • What is meant by "Thread" in "Thread.CurrentThread..." I'm getting "The name Thread" does not exist in the current context" from the compiler. – user316117 Jul 16 '14 at 16:38
  • 1
    @user316117 You probably need a `using System.Threading;` at the top of your code file. "Thread" is the System.Threading.Thread class. – pmcoltrane Jul 16 '14 at 16:44
  • 6
    @user316117 You should really use `CultureInfo ci = (CultureInfo)Thread.CurrentThread.CurrentCulture.Clone();` instead. The reason is that the current culture may or may not `useUserOverride`, and that information is not in `Name`. Also other stuff may have been changed, and that is not visible in `Name`. – Jeppe Stig Nielsen Aug 04 '14 at 01:12
  • 1
    If/when you assign your modified `ci` back to `CurrentCulture`, you may or may not want to make your version read-only as well, i.e. consider `Thread.CurrentThread.CurrentCulture = CultureInfo.ReadOnly(ci);`. – Jeppe Stig Nielsen Aug 04 '14 at 01:14
3

You can use the Clone() method on the NumberFormatInfo instance, which will create a mutable version (i.e. IsReadOnly = false). You are then able set the currency symbol and/or other number format options:

string sep = "."; 
NumberFormatInfo nfi1 = (NumberFormatInfo)NumberFormatInfo.CurrentInfo.Clone();
nfi1.NumberDecimalSeparator = sep;
Jaans
  • 4,598
  • 4
  • 39
  • 49