共用方式為


剖析 .NET 中的數值字串

所有數值類型都有兩個靜態剖析方法,ParseTryParse,可用來將數位的字串表示轉換成數值類型。 這些方法可讓您剖析字串,這些字串是使用記錄於 標準數值格式字串自定義數值格式字串中的格式字串所產生的。 根據預設,ParseTryParse 方法可以成功將包含整數小數字數的字串轉換成整數值。 它們可以成功將包含整數和小數十進位數位、群組分隔符和小數分隔符的字串轉換成浮點值。 如果作業失敗,則 Parse 方法會擲回例外狀況,而 TryParse 方法會傳回 false

備註

從 .NET 7 開始,.NET 中的數值類型也會實作 System.IParsable<TSelf> 介面,該介面會定義 IParsable<TSelf>.ParseIParsable<TSelf>.TryParse 方法。

解析和格式提供者

一般而言,數值的字串表示會因文化特性而異。 數值字串的元素,例如貨幣符號、千位分隔符,以及小數分隔符,都因文化特性而異。 剖析方法以隱含或明確方式使用可辨識涉及文化特殊變異的格式提供者。 如果在呼叫 ParseTryParse 方法時未指定任何格式提供者,則會使用與目前文化特性相關聯的格式提供者(NumberFormatInfo 屬性所傳回 NumberFormatInfo.CurrentInfo 物件)。

格式提供者是由 IFormatProvider 實作表示。 這個介面具有單一成員,GetFormat 方法,其單一參數是代表要格式化之類型的 Type 物件。 這個方法會傳回提供格式信息的物件。 .NET 支援下列兩個 IFormatProvider 實作來剖析數值字串:

下列範例會嘗試將陣列中的每個字串轉換成 Double 值。 它會先嘗試使用反映英文(美國)文化特性慣例的格式提供者來剖析字串。 如果此操作引發 FormatException異常,它會嘗試使用符合法國文化慣例的格式提供者來解析字串。

using System;
using System.Globalization;

public class Example
{
   public static void Main()
   {
      string[] values = { "1,304.16", "$1,456.78", "1,094", "152",
                          "123,45 €", "1 304,16", "Ae9f" };
      double number;
      CultureInfo culture = null;

      foreach (string value in values) {
         try {
            culture = CultureInfo.CreateSpecificCulture("en-US");
            number = Double.Parse(value, culture);
            Console.WriteLine($"{culture.Name}: {value} --> {number}");
         }
         catch (FormatException) {
            Console.WriteLine($"{culture.Name}: Unable to parse '{value}'.");
            culture = CultureInfo.CreateSpecificCulture("fr-FR");
            try {
               number = Double.Parse(value, culture);
               Console.WriteLine($"{culture.Name}: {value} --> {number}");
            }
            catch (FormatException) {
               Console.WriteLine($"{culture.Name}: Unable to parse '{value}'.");
            }
         }
         Console.WriteLine();
      }
   }
}
// The example displays the following output:
//    en-US: 1,304.16 --> 1304.16
//
//    en-US: Unable to parse '$1,456.78'.
//    fr-FR: Unable to parse '$1,456.78'.
//
//    en-US: 1,094 --> 1094
//
//    en-US: 152 --> 152
//
//    en-US: Unable to parse '123,45 €'.
//    fr-FR: Unable to parse '123,45 €'.
//
//    en-US: Unable to parse '1 304,16'.
//    fr-FR: 1 304,16 --> 1304.16
//
//    en-US: Unable to parse 'Ae9f'.
//    fr-FR: Unable to parse 'Ae9f'.
Imports System.Globalization

Module Example
    Public Sub Main()
        Dim values() As String = {"1,304.16", "$1,456.78", "1,094", "152",
                                   "123,45 €", "1 304,16", "Ae9f"}
        Dim number As Double
        Dim culture As CultureInfo = Nothing

        For Each value As String In values
            Try
                culture = CultureInfo.CreateSpecificCulture("en-US")
                number = Double.Parse(value, culture)
                Console.WriteLine("{0}: {1} --> {2}", culture.Name, value, number)
            Catch e As FormatException
                Console.WriteLine("{0}: Unable to parse '{1}'.",
                                  culture.Name, value)
                culture = CultureInfo.CreateSpecificCulture("fr-FR")
                Try
                    number = Double.Parse(value, culture)
                    Console.WriteLine("{0}: {1} --> {2}", culture.Name, value, number)
                Catch ex As FormatException
                    Console.WriteLine("{0}: Unable to parse '{1}'.",
                                      culture.Name, value)
                End Try
            End Try
            Console.WriteLine()
        Next
    End Sub
End Module
' The example displays the following output:
'    en-US: 1,304.16 --> 1304.16
'    
'    en-US: Unable to parse '$1,456.78'.
'    fr-FR: Unable to parse '$1,456.78'.
'    
'    en-US: 1,094 --> 1094
'    
'    en-US: 152 --> 152
'    
'    en-US: Unable to parse '123,45 €'.
'    fr-FR: Unable to parse '123,45 €'.
'    
'    en-US: Unable to parse '1 304,16'.
'    fr-FR: 1 304,16 --> 1304.16
'    
'    en-US: Unable to parse 'Ae9f'.
'    fr-FR: Unable to parse 'Ae9f'.

解析和 NumberStyles 值

剖析作業可以處理的樣式元素(例如空白、群組分隔符號和小數分隔符號),是由 NumberStyles 列舉值所定義。 根據預設,表示整數值的字串會使用 NumberStyles.Integer 值來剖析,只允許數字、前後空格和前導符號。 代表浮點值的字串會使用 NumberStyles.FloatNumberStyles.AllowThousands 值的組合來剖析;這個複合樣式允許小數位數以及開頭和尾端空格符、前置符號、小數分隔符、群組分隔符和指數。 藉由呼叫包含類型 Parse 參數的 TryParseNumberStyles 方法多載,並設定一或多個 NumberStyles 旗標,您可以控制為了讓剖析操作成功,字串中可存在的樣式元素。

例如,包含群組分隔符的字串無法使用 Int32 方法轉換成 Int32.Parse(String) 值。 不過,如果您使用 NumberStyles.AllowThousands 旗標,轉換會成功,如下列範例所示。

using System;
using System.Globalization;

public class Example
{
   public static void Main()
   {
      string value = "1,304";
      int number;
      IFormatProvider provider = CultureInfo.CreateSpecificCulture("en-US");
      if (Int32.TryParse(value, out number))
         Console.WriteLine($"{value} --> {number}");
      else
         Console.WriteLine($"Unable to convert '{value}'");

      if (Int32.TryParse(value, NumberStyles.Integer | NumberStyles.AllowThousands,
                        provider, out number))
         Console.WriteLine($"{value} --> {number}");
      else
         Console.WriteLine($"Unable to convert '{value}'");
   }
}
// The example displays the following output:
//       Unable to convert '1,304'
//       1,304 --> 1304
Imports System.Globalization

Module Example
    Public Sub Main()
        Dim value As String = "1,304"
        Dim number As Integer
        Dim provider As IFormatProvider = CultureInfo.CreateSpecificCulture("en-US")
        If Int32.TryParse(value, number) Then
            Console.WriteLine("{0} --> {1}", value, number)
        Else
            Console.WriteLine("Unable to convert '{0}'", value)
        End If

        If Int32.TryParse(value, NumberStyles.Integer Or NumberStyles.AllowThousands,
                          provider, number) Then
            Console.WriteLine("{0} --> {1}", value, number)
        Else
            Console.WriteLine("Unable to convert '{0}'", value)
        End If
    End Sub
End Module
' The example displays the following output:
'       Unable to convert '1,304'
'       1,304 --> 1304

警告

剖析作業一律會使用特定文化特性的格式設定慣例。 如果您未透過傳遞 CultureInfoNumberFormatInfo 物件來指定文化特性,則會使用與目前線程相關聯的文化特性。

下表列出 NumberStyles 列舉的成員,並描述它們在剖析作業上的效果。

NumberStyles 值 要解析字串所受的影響
NumberStyles.None 只允許數值數位。
NumberStyles.AllowDecimalPoint 允許小數分隔符和小數位數。 針對整數值,只允許零做為小數字數。 有效的小數分隔符是由 NumberFormatInfo.NumberDecimalSeparatorNumberFormatInfo.CurrencyDecimalSeparator 屬性所決定。
NumberStyles.AllowExponent “e” 或 “E” 字元可用來表示指數表示法。 如需詳細資訊,請參閱NumberStyles
NumberStyles.AllowLeadingWhite 允許前置空格符。
NumberStyles.AllowTrailingWhite 允許尾端空格符。
NumberStyles.AllowLeadingSign 正負號可以位於數字之前。
NumberStyles.AllowTrailingSign 數字可以有正號或負號。
NumberStyles.AllowParentheses 括號可用來表示負值。
NumberStyles.AllowThousands 允許群組分隔符。 群組分隔符是由 NumberFormatInfo.NumberGroupSeparatorNumberFormatInfo.CurrencyGroupSeparator 屬性所決定。
NumberStyles.AllowCurrencySymbol 可以使用貨幣符號。 貨幣符號是由 NumberFormatInfo.CurrencySymbol 屬性所定義。
NumberStyles.AllowHexSpecifier 要剖析的字串會解譯為十六進位數位。 它可以包含十六進位數位 0-9、A-F 和 a-f。 這個旗標只能用來剖析整數值。
NumberStyles.AllowBinarySpecifier 要剖析的字串會解譯為二進位數。 它可以包含二進位數位 0 和 1。 這個旗標只能用來剖析整數值。

此外,NumberStyles 列舉提供下列復合樣式,其中包含多個 NumberStyles 旗標。

組合型 NumberStyles 值 包含成員
NumberStyles.Integer 包含 NumberStyles.AllowLeadingWhiteNumberStyles.AllowTrailingWhiteNumberStyles.AllowLeadingSign 樣式。 這是用來剖析整數值的預設樣式。
NumberStyles.Number 包含 NumberStyles.AllowLeadingWhiteNumberStyles.AllowTrailingWhiteNumberStyles.AllowLeadingSignNumberStyles.AllowTrailingSignNumberStyles.AllowDecimalPointNumberStyles.AllowThousands 樣式。
NumberStyles.Float 包含 NumberStyles.AllowLeadingWhiteNumberStyles.AllowTrailingWhiteNumberStyles.AllowLeadingSignNumberStyles.AllowDecimalPointNumberStyles.AllowExponent 樣式。
NumberStyles.Currency 包含 NumberStyles.AllowExponentNumberStyles.AllowHexSpecifier以外的所有樣式。
NumberStyles.Any 包含 NumberStyles.AllowHexSpecifier以外的所有樣式。
NumberStyles.HexNumber 包含 NumberStyles.AllowLeadingWhiteNumberStyles.AllowTrailingWhiteNumberStyles.AllowHexSpecifier 樣式。
NumberStyles.BinaryNumber 包含 NumberStyles.AllowLeadingWhiteNumberStyles.AllowTrailingWhiteNumberStyles.AllowBinarySpecifier 樣式。

解析二進位和十六進位大整數

當使用 AllowHexSpecifierAllowBinarySpecifier 旗標剖析 BigInteger 時,輸入字串會被解譯為其自身長度的十六進位或二進位數。 例如,將 "11" 解析為二進位 BigInteger 會產生 -1,因為這是將 11 解釋為帶符號的兩位數二進制補碼值。 如果您想要正面結果,請新增前置 0,例如 "011" 被解析為 3

剖析和 Unicode 數字

Unicode 標準會定義各種寫入系統中數位的代碼點。 例如,從 U+0030 到 U+0039 的碼位代表基本拉丁數字 0 到 9,從 U+09E6 到 U+09EF 的碼位代表孟加拉數字 0 到 9,而從 U+FF10 到 U+FF19 的碼位代表全形數字 0 到 9。 不過,剖析方法所辨識的唯一數值數位是基本拉丁數位0-9,代碼點從U+0030到U+0039。 如果數值剖析方法傳遞包含任何其他數位的字串,此方法會擲回 FormatException

下列範例會使用 Int32.Parse 方法來剖析字串,這些字串是由不同寫入系統中的數位所組成。 如範例輸出所示,剖析基本拉丁數位的嘗試會成功,但嘗試剖析 Fullwidth、Arabic-Indic 和 Bangla 數位會失敗。

using System;

public class Example
{
   public static void Main()
   {
      string value;
      // Define a string of basic Latin digits 1-5.
      value = "\u0031\u0032\u0033\u0034\u0035";
      ParseDigits(value);

      // Define a string of Fullwidth digits 1-5.
      value = "\uFF11\uFF12\uFF13\uFF14\uFF15";
      ParseDigits(value);

      // Define a string of Arabic-Indic digits 1-5.
      value = "\u0661\u0662\u0663\u0664\u0665";
      ParseDigits(value);

      // Define a string of Bangla digits 1-5.
      value = "\u09e7\u09e8\u09e9\u09ea\u09eb";
      ParseDigits(value);
   }

   static void ParseDigits(string value)
   {
      try {
         int number = Int32.Parse(value);
         Console.WriteLine($"'{value}' --> {number}");
      }
      catch (FormatException) {
         Console.WriteLine($"Unable to parse '{value}'.");
      }
   }
}
// The example displays the following output:
//       '12345' --> 12345
//       Unable to parse '12345'.
//       Unable to parse '١٢٣٤٥'.
//       Unable to parse '১২৩৪৫'.
Module Example
    Public Sub Main()
        Dim value As String
        ' Define a string of basic Latin digits 1-5.
        value = ChrW(&h31) + ChrW(&h32) + ChrW(&h33) + ChrW(&h34) + ChrW(&h35)
        ParseDigits(value)

        ' Define a string of Fullwidth digits 1-5.
        value = ChrW(&hff11) + ChrW(&hff12) + ChrW(&hff13) + ChrW(&hff14) + ChrW(&hff15)
        ParseDigits(value)

        ' Define a string of Arabic-Indic digits 1-5.
        value = ChrW(&h661) + ChrW(&h662) + ChrW(&h663) + ChrW(&h664) + ChrW(&h665)
        ParseDigits(value)

        ' Define a string of Bangla digits 1-5.
        value = ChrW(&h09e7) + ChrW(&h09e8) + ChrW(&h09e9) + ChrW(&h09ea) + ChrW(&h09eb)
        ParseDigits(value)
    End Sub

    Sub ParseDigits(value As String)
        Try
            Dim number As Integer = Int32.Parse(value)
            Console.WriteLine("'{0}' --> {1}", value, number)
        Catch e As FormatException
            Console.WriteLine("Unable to parse '{0}'.", value)
        End Try
    End Sub
End Module
' The example displays the following output:
'       '12345' --> 12345
'       Unable to parse '12345'.
'       Unable to parse '١٢٣٤٥'.
'       Unable to parse '১২৩৪৫'.

另請參閱