Export (0) Print
Expand All

NumberFormatInfo Class

Provides culture-specific information for formatting and parsing numeric values.

System.Object
  System.Globalization.NumberFormatInfo

Namespace:  System.Globalization
Assembly:  mscorlib (in mscorlib.dll)

[SerializableAttribute]
[ComVisibleAttribute(true)]
public sealed class NumberFormatInfo : ICloneable, 
	IFormatProvider

The NumberFormatInfo type exposes the following members.

  NameDescription
Public methodSupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsNumberFormatInfoInitializes a new writable instance of the NumberFormatInfo class that is culture-independent (invariant).
Top

  NameDescription
Public propertySupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsCurrencyDecimalDigitsGets or sets the number of decimal places to use in currency values.
Public propertySupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsCurrencyDecimalSeparatorGets or sets the string to use as the decimal separator in currency values.
Public propertySupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsCurrencyGroupSeparatorGets or sets the string that separates groups of digits to the left of the decimal in currency values.
Public propertySupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsCurrencyGroupSizesGets or sets the number of digits in each group to the left of the decimal in currency values.
Public propertySupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsCurrencyNegativePatternGets or sets the format pattern for negative currency values.
Public propertySupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsCurrencyPositivePatternGets or sets the format pattern for positive currency values.
Public propertySupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsCurrencySymbolGets or sets the string to use as the currency symbol.
Public propertyStatic memberSupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsCurrentInfoGets a read-only NumberFormatInfo that formats values based on the current culture.
Public propertyDigitSubstitutionGets or sets a value that specifies how the graphical user interface displays the shape of a digit.
Public propertyStatic memberSupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsInvariantInfoGets a read-only NumberFormatInfo object that is culture-independent (invariant).
Public propertySupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsIsReadOnlyGets a value that indicates whether this NumberFormatInfo object is read-only.
Public propertySupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsNaNSymbolGets or sets the string that represents the IEEE NaN (not a number) value.
Public propertyNativeDigitsGets or sets a string array of native digits equivalent to the Western digits 0 through 9.
Public propertySupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsNegativeInfinitySymbolGets or sets the string that represents negative infinity.
Public propertySupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsNegativeSignGets or sets the string that denotes that the associated number is negative.
Public propertySupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsNumberDecimalDigitsGets or sets the number of decimal places to use in numeric values.
Public propertySupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsNumberDecimalSeparatorGets or sets the string to use as the decimal separator in numeric values.
Public propertySupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsNumberGroupSeparatorGets or sets the string that separates groups of digits to the left of the decimal in numeric values.
Public propertySupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsNumberGroupSizesGets or sets the number of digits in each group to the left of the decimal in numeric values.
Public propertySupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsNumberNegativePatternGets or sets the format pattern for negative numeric values.
Public propertySupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsPercentDecimalDigitsGets or sets the number of decimal places to use in percent values.
Public propertySupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsPercentDecimalSeparatorGets or sets the string to use as the decimal separator in percent values.
Public propertySupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsPercentGroupSeparatorGets or sets the string that separates groups of digits to the left of the decimal in percent values.
Public propertySupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsPercentGroupSizesGets or sets the number of digits in each group to the left of the decimal in percent values.
Public propertySupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsPercentNegativePatternGets or sets the format pattern for negative percent values.
Public propertySupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsPercentPositivePatternGets or sets the format pattern for positive percent values.
Public propertySupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsPercentSymbolGets or sets the string to use as the percent symbol.
Public propertySupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsPerMilleSymbolGets or sets the string to use as the per mille symbol.
Public propertySupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsPositiveInfinitySymbolGets or sets the string that represents positive infinity.
Public propertySupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsPositiveSignGets or sets the string that denotes that the associated number is positive.
Top

  NameDescription
Public methodSupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsCloneCreates a shallow copy of the NumberFormatInfo object.
Public methodSupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsEquals(Object)Determines whether the specified object is equal to the current object. (Inherited from Object.)
Public methodSupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsGetFormatGets an object of the specified type that provides a number formatting service.
Public methodSupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsGetHashCodeServes as the default hash function. (Inherited from Object.)
Public methodStatic memberSupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsGetInstanceGets the NumberFormatInfo associated with the specified IFormatProvider.
Public methodSupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsGetTypeGets the Type of the current instance. (Inherited from Object.)
Public methodStatic memberSupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsReadOnlyReturns a read-only NumberFormatInfo wrapper.
Public methodSupported by the XNA FrameworkSupported by Portable Class LibrarySupported in .NET for Windows Store appsToStringReturns a string that represents the current object. (Inherited from Object.)
Top

The NumberFormatInfo class contains culture-specific information that is used when you format and parse numeric values. This information includes the currency symbol, the decimal symbol, the group separator symbol, and the symbols for positive and negative signs.

Instantiating a NumberFormatInfo object

You can instantiate a NumberFormatInfo object that represents the formatting conventions of the current culture, the invariant culture, a specific culture, or a neutral culture.

Instantiating a NumberFormatInfo object for the current culture

You can instantiate a NumberFormatInfo object for the current thread culture in any of the following ways. In each case, the returned NumberFormatInfo object is read-only.

The following example uses these three ways to create NumberFormatInfo objects that represent the formatting conventions of the current culture. It also retrieves the value of the IsReadOnly property to illustrate that each object is read-only.

using System;
using System.Globalization;

public class Example
{
   public static void Main()
   {
      NumberFormatInfo current1 = CultureInfo.CurrentCulture.NumberFormat;
      Console.WriteLine(current1.IsReadOnly);

      NumberFormatInfo current2 = NumberFormatInfo.CurrentInfo;
      Console.WriteLine(current2.IsReadOnly);

      NumberFormatInfo current3 = NumberFormatInfo.GetInstance(CultureInfo.CurrentCulture);
      Console.WriteLine(current3.IsReadOnly);
   }
}
// The example displays the following output: 
//       True 
//       True 
//       True

You can create a writable NumberFormatInfo object that represents the conventions of the current thread culture in any of the following ways:

  • By retrieving a NumberFormatInfo object in any of the ways illustrated in the previous code example, and calling the Clone method on the returned NumberFormatInfo object. This creates a copy of the original NumberFormatInfo object, except that its IsReadOnly property is false.

  • By calling the CultureInfo.CreateSpecificCulture method to create a CultureInfo object that represents the current culture, and then using its CultureInfo.NumberFormat property to retrieve the NumberFormatInfo object.

The following example illustrates these two ways of instantiating a NumberFormatInfo object, and displays the value of its IsReadOnly property to illustrate that the object is not read-only.

using System;
using System.Globalization;

public class Example
{
   public static void Main()
   {
      NumberFormatInfo current1 = NumberFormatInfo.CurrentInfo;
      current1 = (NumberFormatInfo) current1.Clone();
      Console.WriteLine(current1.IsReadOnly);

      CultureInfo culture2 = CultureInfo.CreateSpecificCulture(CultureInfo.CurrentCulture.Name);
      NumberFormatInfo current2 = culture2.NumberFormat;
      Console.WriteLine(current2.IsReadOnly);
   }
}
// The example displays the following output: 
//       False 
//       False

Note that the Windows operating system allows the user to override some of the NumberFormatInfo property values used in numeric formatting and parsing operations through the Region and Language item in Control Panel. For example, a user whose culture is English (United States) might choose to display currency values as 1.1 USD instead of the default of $1.1. The NumberFormatInfo objects retrieved in the ways discussed previously all reflect these user overrides. If this is undesirable, you can create a NumberFormatInfo object that does not reflect user overrides (and that is also read/write rather than read-only) by calling the CultureInfo.CultureInfo(String, Boolean) constructor and supplying a value of false for the useUserOverride argument. The following example provides an illustration for a system whose current culture is English (United States) and whose currency symbol has been changed from the default of $ to USD.

using System;
using System.Globalization;

public class Example
{
   public static void Main()
   {
      CultureInfo culture;
      NumberFormatInfo nfi;

      culture = CultureInfo.CurrentCulture;
      nfi = culture.NumberFormat;
      Console.WriteLine("Culture Name:    {0}", culture.Name);
      Console.WriteLine("User Overrides:  {0}", culture.UseUserOverride);
      Console.WriteLine("Currency Symbol: {0}\n", culture.NumberFormat.CurrencySymbol);

      culture = new CultureInfo(CultureInfo.CurrentCulture.Name, false);
      Console.WriteLine("Culture Name:    {0}", culture.Name);
      Console.WriteLine("User Overrides:  {0}", culture.UseUserOverride);
      Console.WriteLine("Currency Symbol: {0}", culture.NumberFormat.CurrencySymbol);
   }
}
// The example displays the following output: 
//       Culture Name:    en-US 
//       User Overrides:  True 
//       Currency Symbol: USD 
//        
//       Culture Name:    en-US 
//       User Overrides:  False 
//       Currency Symbol: $

If the CultureInfo.UseUserOverride property is set to true, the properties CultureInfo.DateTimeFormat, CultureInfo.NumberFormat, and CultureInfo.TextInfo are also retrieved from the user settings. If the user settings are incompatible with the culture associated with the CultureInfo object (for example, if the selected calendar is not one of the calendars listed by the OptionalCalendars property), the results of the methods and the values of the properties are undefined.

Instantiating a NumberFormatInfo object for the invariant culture

The invariant culture represents a culture that is culture-insensitive. It is based on the English language but not on any specific English-speaking country/region. Although the data of specific cultures can be dynamic and can change to reflect new cultural conventions or user preferences, the data of the invariant culture does not change. A NumberFormatInfo object that represents the formatting conventions of the invariant culture can be used for formatting operations in which result strings should not vary by culture.

You can instantiate a NumberFormatInfo object that represents the formatting conventions of the invariant culture in the following ways:

The following example uses each of these methods to instantiate a NumberFormatInfo object that represents the invariant culture. It then indicates whether the object is read-only,

using System;
using System.Globalization;

public class Example
{
   public static void Main()
   {
      NumberFormatInfo nfi;

      nfi = System.Globalization.NumberFormatInfo.InvariantInfo;
      Console.WriteLine(nfi.IsReadOnly);               

      nfi = CultureInfo.InvariantCulture.NumberFormat;
      Console.WriteLine(nfi.IsReadOnly);               

      nfi = New NumberFormatInfo();
      Console.WriteLine(nfi.IsReadOnly);               
   }
}
// The example displays the following output: 
//       True 
//       True 
//       False

Instantiating a NumberFormatInfo object for a specific culture

A specific culture represents a language that is spoken in a particular country/region. For example, en-US is a specific culture that represents the English language spoken in the United States, and en-CA is a specific culture that represents the English language spoken in Canada. You can instantiate a NumberFormatInfo object that represents the formatting conventions of a specific culture in the following ways:

The following example uses these four ways to create a NumberFormatInfo object that reflects the formatting conventions of the Indonesian (Indonesia) culture. It also indicates whether each object is read-only.

using System;
using System.Globalization;

public class Example
{
   public static void Main()
   {
      CultureInfo culture;
      NumberFormatInfo nfi;

      nfi = CultureInfo.GetCultureInfo("id-ID").NumberFormat;
      Console.WriteLine("Read-only: {0}", nfi.IsReadOnly);

      culture = new CultureInfo("id-ID");
      nfi = NumberFormatInfo.GetInstance(culture);
      Console.WriteLine("Read-only: {0}", nfi.IsReadOnly);

      culture = CultureInfo.CreateSpecificCulture("id-ID");
      nfi = culture.NumberFormat;
      Console.WriteLine("Read-only: {0}", nfi.IsReadOnly);

      culture = new CultureInfo("id-ID");
      nfi = culture.NumberFormat;
      Console.WriteLine("Read-only: {0}", nfi.IsReadOnly);
   }
}
// The example displays the following output: 
//       Read-only: True 
//       Read-only: False 
//       Read-only: False 
//       Read-only: False

Instantiating a NumberFormatInfo object for a neutral culture

A neutral culture represents a culture or language that is independent of a country/region. It is typically the parent of one or more specific cultures. For example, fr is a neutral culture for the French language and the parent of the fr-FR culture. You create a NumberFormatInfo object that represents the formatting conventions of a neutral culture in the same way that you create a NumberFormatInfo object that represents the formatting conventions of a specific culture.

NoteNote

In the .NET Framework 3.5 and earlier versions, trying to retrieve a NumberFormatInfo object that reflects the formatting conventions of a neutral culture throws a NotSupportedException exception.

However, because it is independent of a specific country/region, a neutral culture lacks culture-specific formatting information. Rather than populating the NumberFormatInfo object with generic values, the .NET Framework returns a NumberFormatInfo object that reflects the formatting conventions of a specific culture that is a child of the neutral culture. For example, the NumberFormatInfo object for the neutral en culture reflects the formatting conventions of the en-US culture, and the NumberFormatInfo object for the fr culture reflects the formatting conventions of the fr-FR culture.

You can use code like the following to determine which specific culture's formatting conventions each neutral culture represents.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;

public class Example
{
   public static void Main()
   {
      // Get all the neutral cultures
      List<String> names = new List<String>();
      Array.ForEach(CultureInfo.GetCultures(CultureTypes.NeutralCultures),
                    culture => names.Add(culture.Name));
      names.Sort();
      foreach (var name in names) {
         // Ignore the invariant culture. 
         if (name == "") continue;

         ListSimilarChildCultures(name);        
      }
   }

   private static void ListSimilarChildCultures(string name)
   { 
      // Create the neutral NumberFormatInfo object.
      NumberFormatInfo nfi = CultureInfo.GetCultureInfo(name).NumberFormat;
      // Retrieve all specific cultures of the neutral culture.
      CultureInfo[] cultures = Array.FindAll(CultureInfo.GetCultures(CultureTypes.SpecificCultures), 
                               culture => culture.Name.StartsWith(name + "-", StringComparison.OrdinalIgnoreCase));
      // Create an array of NumberFormatInfo properties
      PropertyInfo[] properties = typeof(NumberFormatInfo).GetProperties(BindingFlags.Instance | BindingFlags.Public);
      bool hasOneMatch = false;

      foreach (var ci in cultures) {
         bool match = true;     
         // Get the NumberFormatInfo for a specific culture.
         NumberFormatInfo specificNfi = ci.NumberFormat;
         // Compare the property values of the two. 
         foreach (var prop in properties) {
            // We're not interested in the value of IsReadOnly.      
            if (prop.Name == "IsReadOnly") continue;

            // For arrays, iterate the individual elements to see if they are the same. 
            if (prop.PropertyType.IsArray) { 
               IList nList = (IList) prop.GetValue(nfi, null);
               IList sList = (IList) prop.GetValue(specificNfi, null);
               if (nList.Count != sList.Count) {
                  match = false;
                  break;
               } 

               for (int ctr = 0; ctr < nList.Count; ctr++) {
                  if (! nList[ctr].Equals(sList[ctr])) {
                     match = false;
                     break;
                  }     
               }
            }   
            else if (! prop.GetValue(specificNfi).Equals(prop.GetValue(nfi))) {
               match = false;
               break;   
            }        
         }
         if (match) {
            Console.WriteLine("NumberFormatInfo object for '{0}' matches '{1}'", 
                                      name, ci.Name);
            hasOneMatch = true;
         }                                       
      }
      if (! hasOneMatch)
         Console.WriteLine("NumberFormatInfo object for '{0}' --> No Match", name);            

      Console.WriteLine();
   }
}

NumberFormatInfo and dynamic data

The culture-specific data for formatting numeric values provided by the NumberFormatInfo class is dynamic, just like the cultural data provided by the CultureInfo class. You should not make any assumptions about the stability of values for NumberFormatInfo objects that are associated with particular CultureInfo objects. Only the data provided by the invariant culture and its associated NumberFormatInfo object is stable. Other data can change between application sessions, or even within a single session, for the following reasons:

  • System updates. Cultural preferences such as the currency symbol or currency formats change over time. When this happens, Windows Update includes changes to the NumberFormatInfo property value for a particular culture.

  • Replacement cultures. The CultureAndRegionInfoBuilder class can be used to replace the data of an existing culture.

  • Cascading changes to property values. A number of culture-related properties can change at run time, which, in turn, causes NumberFormatInfo data to change. For example, the current culture can be changed either programmatically or through user action. When this happens, the NumberFormatInfo object returned by the CurrentInfo property changes to an object associated with the current culture.

  • User preferences. Users of your application might override some of the values associated with the current system culture through the region and language options in Control Panel. For example, users might choose a different currency symbol or a different decimal separator symbol. If the CultureInfo.UseUserOverride property is set to true (its default value), the properties of the NumberFormatInfo object are also retrieved from the user settings.

Starting with the .NET Framework 2.0, all user-overridable properties of a NumberFormatInfo object are initialized when the object is created. There is still a possibility of inconsistency, because neither object creation nor the user override process is atomic, and the relevant values may change during object creation. However, these inconsistencies should be extremely rare.

You can control whether user overrides are reflected in NumberFormatInfo objects that represent the same culture as the current thread culture. The following table lists the ways in which a NumberFormatInfo object can be retrieved and indicates whether the resulting object reflects user overrides.

Source of CultureInfo and NumberFormatInfo object

Reflects user overrides

CultureInfo.CurrentCulture.NumberFormat property

Yes

NumberFormatInfo.CurrentInfo property

Yes

CultureInfo.CreateSpecificCulture method

Yes

CultureInfo.GetCultureInfo method

No

CultureInfo(String) constructor

Yes

CultureInfo.CultureInfo(String, Boolean) constructor

Depends on value of useUserOverride parameter

Unless there is a compelling reason to do otherwise, you should respect user overrides when you use the NumberFormatInfo object in client applications to format and parse user input or to display numeric data. For server applications or unattended applications, you should not respect user overrides. However, if you are using the NumberFormatInfo object either explicitly or implicitly to persist numeric data in string form, you should either use a NumberFormatInfo object that reflects the formatting conventions of the invariant culture, or you should specify a custom numeric format string that you use regardless of culture.

IFormatProvider, NumberFormatInfo, and numeric formatting

A NumberFormatInfo object is used implicitly or explicitly in all numeric formatting operations. These include calls to the following methods:

All numeric formatting operations make use of an IFormatProvider implementation. The IFormatProvider interface includes a single method, GetFormat(Type). This is a callback method that is passed a Type object that represents the type needed to provide formatting information. The method is responsible for returning either an instance of that type or null, if it cannot provide an instance of the type. The .NET Framework provides two IFormatProvider implementations for formatting numbers:

  • The CultureInfo class, which represents a specific culture (or a specific language in a specific country/region). In a numeric formatting operation, the CultureInfo.GetFormat method returns the NumberFormatInfo object associated with its CultureInfo.NumberFormat property.

  • The NumberFormatInfo class, which provides information about the formatting conventions of its associated culture. The NumberFormatInfo.GetFormat method returns an instance of itself.

If an IFormatProvider implementation is not provided to a formatting method explicitly, a CultureInfo object returned by the CultureInfo.CurrentCulture property that represents the current thread culture is used.

The following example illustrates the relationship between the IFormatProvider interface and the NumberFormatInfo class in formatting operations by defining a custom IFormatProvider implementation. Its GetFormat method displays the type name of the object requested by the formatting operation. If the interface is requesting a NumberFormatInfo object, this method provides the NumberFormatInfo object for the current thread culture. As the output from the example shows, the Decimal.ToString(IFormatProvider) method requests a NumberFormatInfo object to provide formatting information, whereas the String.Format(IFormatProvider, String, Object[]) method requests NumberFormatInfo and DateTimeFormatInfo objects as well as an ICustomFormatter implementation.

using System;
using System.Globalization;

public class CurrentCultureFormatProvider : IFormatProvider
{
   public Object GetFormat(Type formatType) 
   {
      Console.WriteLine("Requesting an object of type {0}", 
                        formatType.Name);
      if (formatType == typeof(NumberFormatInfo))
         return NumberFormatInfo.CurrentInfo;
      else if (formatType == typeof(DateTimeFormatInfo))
         return DateTimeFormatInfo.CurrentInfo;
      else 
         return null;
   }
}

public class Example
{
   public static void Main()
   {
      Decimal amount = 1203.541m;
      string value = amount.ToString("C2", new CurrentCultureFormatProvider());
      Console.WriteLine(value);
      Console.WriteLine();
      string composite = String.Format(new CurrentCultureFormatProvider(), 
                                       "Date: {0}   Amount: {1}   Description: {2}",
                                       DateTime.Now, 1264.03m, "Service Charge");
      Console.WriteLine(composite);
      Console.WriteLine();
   }
}
// The example displays output like the following: 
//    Requesting an object of type NumberFormatInfo 
//    $1,203.54 
//     
//    Requesting an object of type ICustomFormatter 
//    Requesting an object of type DateTimeFormatInfo 
//    Requesting an object of type NumberFormatInfo 
//    Date: 11/15/2012 2:00:01 PM   Amount: 1264.03   Description: Service Charge

If an IFormatProvider implementation is not explicitly provided in a numeric formatting method call, the method calls the CultureInfo.CurrentCulture.GetFormat method, which returns the NumberFormatInfo object that corresponds to the current thread culture.

Format strings and NumberFormatInfo properties

Every formatting operation uses either a standard or a custom numeric format string to produce a result string from a number. In some cases, the use of a format string to produce a result string is explicit, as in the following example. This code calls the Decimal.ToString(IFormatProvider) method to convert a Decimal value to a number of different string representations by using the formatting conventions of the en-US culture.

using System;
using System.Globalization;

public class Example
{
   public static void Main()
   {
      string[] formatStrings = { "C2", "E1", "F", "G3", "N", 
                                 "#,##0.000", "0,000,000,000.0##" };
      CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");
      Decimal[] values = { 1345.6538m, 1921651.16m };

      foreach (var value in values) {
         foreach (var formatString in formatStrings) {
            string resultString = value.ToString(formatString, culture);
            Console.WriteLine("{0,-18} -->  {1}", formatString, resultString);
         }
         Console.WriteLine();      
      }   
   }
}
// The example displays the following output: 
//       C2                 -->  $1,345.65 
//       E1                 -->  1.3E+003 
//       F                  -->  1345.65 
//       G3                 -->  1.35E+03 
//       N                  -->  1,345.65 
//       #,##0.000          -->  1,345.654 
//       0,000,000,000.0##  -->  0,000,001,345.654 
//        
//       C2                 -->  $1,921,651.16 
//       E1                 -->  1.9E+006 
//       F                  -->  1921651.16 
//       G3                 -->  1.92E+06 
//       N                  -->  1,921,651.16 
//       #,##0.000          -->  1,921,651.160 
//       0,000,000,000.0##  -->  0,001,921,651.16

In other cases, the use of a format string is implicit. For example, in the following method calls to the default or parameterless Decimal.ToString() method, the value of the Decimal instance is formatted by using the general ("G") format specifier and the conventions of the current culture, which in this case is the en-US culture.

using System;

public class Example
{
   public static void Main()
   {
      Decimal[] values = { 1345.6538m, 1921651.16m };

      foreach (var value in values) {
         string resultString = value.ToString();
         Console.WriteLine(resultString);
         Console.WriteLine();      
      }   
   }
}
// The example displays the following output: 
//       1345.6538 
//        
//       1921651.16

Each standard numeric format string uses one or more NumberFormatInfo properties to determine the pattern or the symbols used in the result string. Similarly, each custom numeric format specifier except "0" and "#" insert symbols in the result string that are defined by NumberFormatInfo properties. The following table lists the standard and custom numeric format specifiers and their associated NumberFormatInfo properties. To change the appearance of the result string for a particular culture, see the Modifying NumberFormatInfo properties section. For details about the use of these format specifiers, see Standard Numeric Format Strings and Custom Numeric Format Strings.

Format specifier

Associated properties

"C" or "c" (currency format specifier)

CurrencyDecimalDigits, to define the default number of fractional digits.

CurrencyDecimalSeparator, to define the decimal separator symbol.

CurrencyGroupSeparator, to define the group or thousands separator.

CurrencyGroupSizes, to define the sizes of integral groups.

CurrencyNegativePattern, to define the pattern of negative currency values.

CurrencyPositivePattern, to define the pattern of positive currency values.

CurrencySymbol, to define the currency symbol.

NegativeSign, to define the negative sign symbol.

"D" or "d" (decimal format specifier)

NegativeSign, to define the negative sign symbol.

"E" or "e" (exponential or scientific format specifier)

NegativeSign, to define the negative sign symbol in the mantissa and exponent.

NumberDecimalSeparator, to define the decimal separator symbol.

PositiveSign, to define the positive sign symbol in the exponent.

"F" or "f" (fixed-point format specifier)

NegativeSign, to define the negative sign symbol.

NumberDecimalDigits, to define the default number of fractional digits.

NumberDecimalSeparator, to define the decimal separator symbol.

"G" or "g" (general format specifier)

NegativeSign, to define the negative sign symbol.

NumberDecimalSeparator, to define the decimal separator symbol.

PositiveSign, to define the positive sign symbol for result strings in exponential format.

"N" or "n" (number format specifier)

NegativeSign, to define the negative sign symbol.

NumberDecimalDigits, to define the default number of fractional digits.

NumberDecimalSeparator, to define the decimal separator symbol.

NumberGroupSeparator, to define the group separator (thousands) symbol.

NumberGroupSizes, to define the number of integral digits in a group.

NumberNegativePattern, to define the format of negative values.

"P" or "p" (percent format specifier)

NegativeSign, to define the negative sign symbol.

PercentDecimalDigits, to define the default number of fractional digits.

PercentDecimalSeparator, to define the decimal separator symbol.

PercentGroupSeparator, to define the group separator symbol.

PercentGroupSizes, to define the number of integral digits in a group.

PercentNegativePattern, to define the placement of the percent symbol and the negative symbol for negative values.

PercentPositivePattern, to define the placement of the percent symbol for positive values.

PercentSymbol, to define the percent symbol.

"R" or "r" (round-trip format specifier)

NegativeSign, to define the negative sign symbol.

NumberDecimalSeparator, to define the decimal separator symbol.

PositiveSign, to define the positive sign symbol in an exponent.

"X" or "x" (hexadecimal format specifier)

None.

"." (decimal point custom format specifier)

NumberDecimalSeparator, to define the decimal separator symbol.

"," (group separator custom format specifier)

NumberGroupSeparator, to define the group (thousands) separator symbol.

"%" (percentage placeholder custom format specifier)

PercentSymbol, to define the percent symbol.

"‰" (per mille placeholder custom format specifier)

PerMilleSymbol, to define the per mille symbol.

"E" (exponential notation custom format specifier)

NegativeSign, to define the negative sign symbol in the mantissa and exponent.

PositiveSign, to define the positive sign symbol in the exponent.

Note that the NumberFormatInfo class includes a NativeDigits property that specifies the base 10 digits used by a specific culture. However, the property is not used in formatting operations; only the Basic Latin digits 0 (U+0030) through 9 (U+0039) are used in the result string. In addition, for Single and Double values of NaN, PositiveInfinity, and NegativeInfinity, the result string consists exclusively of the symbols defined by the NaNSymbol, PositiveInfinitySymbol, and NegativeInfinitySymbol properties, respectively.

Modifying NumberFormatInfo properties

You can modify the properties of a NumberFormatInfo object to customize the result string produced in a numeric formatting operation. To do this:

  1. Create a read/write copy of a NumberFormatInfo object whose formatting conventions you want to modify. For more information, see the Instantiating a NumberFormatInfo object section.

  2. Modify the property or properties that are used to produce the desired result string. For information about how formatting methods use NumberFormatInfo properties to define result strings, see the Format strings and NumberFormatInfo properties section.

  3. Use the custom NumberFormatInfo object as the IFormatProvider argument in calls to formatting methods.

NoteNote

Instead of dynamically modifying a culture's property values each time an application is started, you can use the CultureAndRegionInfoBuilder class to define either a custom culture (a culture that has a unique name and that supplements existing cultures) or a replacement culture (one that is used instead of a specific culture).

The following sections provide some examples.

The following example modifies a NumberFormatInfo object that that represents the formatting conventions of the en-US culture. It assigns the ISO-4217 currency symbol to the CurrencySymbol property and defines a pattern for currency values that consists of the currency symbol followed by a space and a numeric value.

using System;
using System.Globalization;

public class Example
{
   public static void Main()
   {
      // Retrieve a writable NumberFormatInfo object.
      CultureInfo enUS = CultureInfo.CreateSpecificCulture("en-US");
      NumberFormatInfo nfi = enUS.NumberFormat;

      // Use the ISO currency symbol instead of the native currency symbol.
      nfi.CurrencySymbol =  (new RegionInfo(enUS.Name)).ISOCurrencySymbol;
      // Change the positive currency pattern to <code><space><value>.
      nfi.CurrencyPositivePattern = 2;
      // Change the negative currency pattern to <code><space><sign><value>.     
      nfi.CurrencyNegativePattern = 12;

      // Produce the result strings by calling ToString.
      Decimal[] values = { 1065.23m, 19.89m, -.03m, -175902.32m };
      foreach (var value in values)
         Console.WriteLine(value.ToString("C", enUS));

      Console.WriteLine();

      // Produce the result strings by calling a composite formatting method. 
      foreach (var value in values)
         Console.WriteLine(String.Format(enUS, "{0:C}", value));      
   }
}
// The example displays the following output: 
//       USD 1,065.23 
//       USD 19.89 
//       USD -0.03 
//       USD -175,902.32 
//        
//       USD 1,065.23 
//       USD 19.89 
//       USD -0.03 
//       USD -175,902.32

Many national identification numbers consist exclusively of digits and so can easily be formatted by modifying the properties of a NumberFormatInfo object. For example, a social security number in the United States consists of 9 digits arranged as follows: XXX-XX-XXXX. The following example assumes that social security numbers are stored as integer values and formats them appropriately.

using System;
using System.Globalization;

public class Example
{
   public static void Main()
   {
      // Instantiate a read-only NumberFormatInfo object.
      CultureInfo enUS = CultureInfo.CreateSpecificCulture("en-US");
      NumberFormatInfo nfi = enUS.NumberFormat;

      // Modify the relevant properties.
      nfi.NumberGroupSeparator = "-";
      nfi.NumberGroupSizes = new int[] { 3, 2, 4};
      nfi.NumberDecimalDigits = 0;

      int[] ids = { 111223333, 999776666 };

      // Produce the result string by calling ToString. 
      foreach (var id in ids)
         Console.WriteLine(id.ToString("N", enUS));

      Console.WriteLine();

      // Produce the result string using composite formatting. 
      foreach (var id in ids)
         Console.WriteLine(String.Format(enUS, "{0:N}", id));
   }
}
// The example displays the following output: 
//       1112-23-333 
//       9997-76-666 
//        
//       1112-23-333 
//       9997-76-666

Parsing numeric strings

Parsing involves converting the string representation of a number to a number. Each numeric type in the .NET Framework includes two overloaded parsing methods: Parse and TryParse. The Parse method converts a string to a number and throws an exception if the conversion fails. The TryParse method converts a string to a number, assigns the number to an out argument, and returns a Boolean value that indicates whether the conversion succeeded.

The parsing methods implicitly or explicitly use a NumberStyles enumeration value to determine what style elements (such as group separators, a decimal separator, or a currency symbol) can be present in a string if the parsing operation is to succeed. If a NumberStyles value is not provided in the method call, the default is a NumberStyles value that includes the Float and AllowThousands flags, which specifies that the parsed string can include group symbols, a decimal separator, a negative sign, and white-space characters, or it can be the string representation of a number in exponential notation.

The parsing methods also implicitly or explicitly use a NumberFormatInfo object that defines the specific symbols and patterns that can occur in the string to be parsed. If a NumberFormatInfo object is not provided, the default is the NumberFormatInfo for the current thread culture. For more information about parsing, see the individual parsing methods, such as Int16.Parse(String), Int32.Parse(String, NumberStyles), Int64.Parse(String, IFormatProvider), Decimal.Parse(String, NumberStyles, IFormatProvider), Double.TryParse(String, Double), and BigInteger.TryParse(String, NumberStyles, IFormatProvider, BigInteger).

The following example illustrates the culture-sensitive nature of parsing strings. It tries to parse a string that include thousands separators by using the conventions of the en-US, fr-FR, and invariant cultures. A string that includes the comma as a group separator and the period as a decimal separator fails to parse in the fr-FR culture, and a string with white space as a group separator and a comma as a decimal separator fails to parse in the en-US and invariant cultures.

using System;
using System.Globalization;

public class Example
{
   public static void Main()
   {
      String[] values = { "1,034,562.91", "9 532 978,07" };
      String[] cultureNames = { "en-US", "fr-FR", "" };

      foreach (var value in values) {
         foreach (var cultureName in cultureNames) {
            CultureInfo culture = CultureInfo.CreateSpecificCulture(cultureName);
            String name = culture.Name == "" ? "Invariant" : culture.Name;
            try {
               Decimal amount = Decimal.Parse(value, culture);
               Console.WriteLine("'{0}' --> {1} ({2})", value, amount, name);
            }
            catch (FormatException) {
               Console.WriteLine("'{0}': FormatException ({1})",
                                 value, name);
            }   
         }
         Console.WriteLine();
      }
   }
}
// The example displays the following output: 
//       '1,034,562.91' --> 1034562.91 (en-US) 
//       '1,034,562.91': FormatException (fr-FR) 
//       '1,034,562.91' --> 1034562.91 (Invariant) 
//        
//       '9 532 978,07': FormatException (en-US) 
//       '9 532 978,07' --> 9532978.07 (fr-FR) 
//       '9 532 978,07': FormatException (Invariant)

Parsing generally occurs in two contexts:

  • As an operation that is designed to convert user input into a numeric value.

  • As an operation that is designed to round-trip a numeric value; that is, to deserialize a numeric value that was previously serialized as a string.

The following sections discuss these two operations in greater detail.

When you are parsing numeric strings input by the user, you should always instantiate a NumberFormatInfo object that reflects the user's cultural settings. For information about how to instantiate a NumberFormatInfo object that reflects user customizations, see the NumberFormatInfo and dynamic data section.

The following example illustrates the difference between a parsing operation that reflects user cultural settings and one that does not. In this case, the default system culture is en-US, but the user has defined "," as the decimal symbol and "." as the group separator in Control Panel, Region and Language. Ordinarily, these symbols are reversed in the default en-US culture. When the user enters a string that reflects user settings, and the string is parsed by a NumberFormatInfo object that also reflects user settings (overrides), the parsing operation returns a correct result. However, when the string is parsed by a NumberFormatInfo object that reflects standard en-US cultural settings, it mistakes the comma symbol for a group separator and returns an incorrect result.

using System;
using System.Globalization;

public class Example
{
   public static void Main()
   {
      CultureInfo stdCulture = CultureInfo.GetCultureInfo("en-US");
      CultureInfo custCulture = CultureInfo.CreateSpecificCulture("en-US"); 

      String value = "310,16";
      try {
         Console.WriteLine("{0} culture reflects user overrides: {1}", 
                           stdCulture.Name, stdCulture.UseUserOverride);
         Decimal amount = Decimal.Parse(value, stdCulture);
         Console.WriteLine("'{0}' --> {1}", value, amount.ToString(CultureInfo.InvariantCulture));                                                                                        
      }
      catch (FormatException) {
         Console.WriteLine("Unable to parse '{0}'", value);
      }    
      Console.WriteLine();

      try {
         Console.WriteLine("{0} culture reflects user overrides: {1}", 
                           custCulture.Name, custCulture.UseUserOverride);
         Decimal amount = Decimal.Parse(value, custCulture);
         Console.WriteLine("'{0}' --> {1}", value, amount.ToString(CultureInfo.InvariantCulture));                                                                                        
      }
      catch (FormatException) {
         Console.WriteLine("Unable to parse '{0}'", value);
      }   
   }
}
// The example displays the following output: 
//       en-US culture reflects user overrides: False 
//       '310,16' --> 31016 
//        
//       en-US culture reflects user overrides: True 
//       '310,16' --> 310.16

When numeric data is serialized in string format and later deserialized and parsed, the strings should be generated and parsed by using the conventions of the invariant culture. The formatting and parsing operations should never reflect the conventions of a specific culture. If culture-specific settings are used, the portability of the data is strictly limited; it can be successfully deserialized only on a thread whose culture-specific settings are identical to those of the thread on which it was serialized. In some cases, this means that the data cannot even be successfully deserialized on the same system on which it was serialized.

The following example illustrates what can happen when this principle is violated. Floating-point values in an array are converted to strings when the current thread uses the culture-specific settings of the en-US culture. The data is then parsed by a thread that uses the culture-specific settings of the en-GB culture. In this case, although each parsing operation succeeds, the data does not round-trip successfully and data corruption occurs. In other cases, a parsing operation could fail and a FormatException exception could be thrown.

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Threading;

public class Example
{
   public static void Main()
   {
      Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-US");
      PersistData();

      Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-GB");
      RestoreData();
   }

   private static void PersistData()
   {
      // Define an array of floating-point values.
      Double[] values = { 160325.972, 8631.16, 1.304e5, 98017554.385, 
                          8.5938287084321676e94 };
      Console.WriteLine("Original values: ");
      foreach (var value in values) 
         Console.WriteLine(value.ToString("R", CultureInfo.InvariantCulture));

      // Serialize an array of doubles to a file 
      StreamWriter sw = new StreamWriter(@".\NumericData.bin");
      for (int ctr = 0; ctr < values.Length; ctr++) {
         sw.Write(values[ctr].ToString("R"));
         if (ctr < values.Length - 1) sw.Write("|");
      }
      sw.Close();
      Console.WriteLine();
   }

   private static void RestoreData()
   {   
      // Deserialize the data
      StreamReader sr = new StreamReader(@".\NumericData.bin");
      String data = sr.ReadToEnd();
      sr.Close();

      String[] stringValues = data.Split('|');
      List<Double> newValueList = new List<Double>();

      foreach (var stringValue in stringValues) {
         try {
            newValueList.Add(Double.Parse(stringValue));
         }
         catch (FormatException) {
            newValueList.Add(Double.NaN);
         }   
      }                                   

      Console.WriteLine("Restored values:");
      foreach (var newValue in newValueList) 
         Console.WriteLine(newValue.ToString("R", NumberFormatInfo.InvariantInfo));
   }
}
// The example displays the following output: 
//       Original values: 
//       160325.972 
//       8631.16 
//       130400 
//       98017554.385 
//       8.5938287084321671E+94 
//        
//       Restored values: 
//       160325972 
//       863116 
//       130400 
//       98017554385 
//       8.5938287084321666E+110

The following example shows how to retrieve a NumberFormatInfo object for a corresponding CultureInfo object, and use the retrieved object to query number formatting information for the particular culture.

using System;
using System.Globalization;
using System.Text;

public sealed class App 
{
    static void Main() 
    {
        StringBuilder sb = new StringBuilder();

        // Loop through all the specific cultures known to the CLR. 
        foreach (CultureInfo ci in CultureInfo.GetCultures(CultureTypes.SpecificCultures)) 
        {
            // Only show the currency symbols for cultures that speak English. 
            if (ci.TwoLetterISOLanguageName != "en") continue;

            // Display the culture name and currency symbol.
            NumberFormatInfo nfi = ci.NumberFormat;
            sb.AppendFormat("The currency symbol for '{0}' is '{1}'",
                ci.DisplayName, nfi.CurrencySymbol);
            sb.AppendLine();
        }
        Console.WriteLine(sb.ToString());
    }
}

// This code produces the following output. 
// 
// The currency symbol for 'English (United States)' is '$' 
// The currency symbol for 'English (United Kingdom)' is '�' 
// The currency symbol for 'English (Australia)' is '$' 
// The currency symbol for 'English (Canada)' is '$' 
// The currency symbol for 'English (New Zealand)' is '$' 
// The currency symbol for 'English (Ireland)' is '?' 
// The currency symbol for 'English (South Africa)' is 'R' 
// The currency symbol for 'English (Jamaica)' is 'J$' 
// The currency symbol for 'English (Caribbean)' is '$' 
// The currency symbol for 'English (Belize)' is 'BZ$' 
// The currency symbol for 'English (Trinidad and Tobago)' is 'TT$' 
// The currency symbol for 'English (Zimbabwe)' is 'Z$' 
// The currency symbol for 'English (Republic of the Philippines)' is 'Php'

.NET Framework

Supported in: 4.5.2, 4.5.1, 4.5, 4, 3.5, 3.0, 2.0, 1.1, 1.0

.NET Framework Client Profile

Supported in: 4, 3.5 SP1

Portable Class Library

Supported in: Portable Class Library

.NET for Windows Store apps

Supported in: Windows 8

.NET for Windows Phone apps

Supported in: Windows Phone 8.1, Windows Phone 8, Silverlight 8.1

Windows Phone 8.1, Windows Phone 8, Windows 8.1, Windows Server 2012 R2, Windows 8, Windows Server 2012, Windows 7, Windows Vista SP2, Windows Server 2008 (Server Core Role not supported), Windows Server 2008 R2 (Server Core Role supported with SP1 or later; Itanium not supported)

The .NET Framework does not support all versions of every platform. For a list of the supported versions, see .NET Framework System Requirements.

Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.
Show:
© 2014 Microsoft