Analizowanie ciągów liczbowych na platformie .NET

Wszystkie typy liczbowe mają dwie statyczne metody analizowania i ParseTryParse, których można użyć do przekonwertowania reprezentacji ciągu liczby na typ liczbowy. Te metody umożliwiają analizowanie ciągów, które zostały wygenerowane przy użyciu ciągów formatu udokumentowanych w standardowych ciągach formatu liczbowego i niestandardowych ciągów formatu liczbowego. Domyślnie Parse metody i TryParse mogą pomyślnie konwertować ciągi zawierające cyfry dziesiętne całkowite tylko na wartości całkowite. Mogą one pomyślnie przekonwertować ciągi zawierające cyfry całkowite i ułamkowe dziesiętne, separatory grup i separator dziesiętny na wartości zmiennoprzecinkowe. Metoda Parse zgłasza wyjątek, jeśli operacja zakończy się niepowodzeniem, podczas gdy TryParse metoda zwraca wartość false.

Uwaga

Począwszy od platformy .NET 7, typy liczbowe na platformie .NET implementują System.IParsable<TSelf> również interfejs, który definiuje IParsable<TSelf>.Parse metody i IParsable<TSelf>.TryParse .

Analizowanie i formatowanie dostawców

Zazwyczaj reprezentacje ciągów wartości liczbowych różnią się kulturą. Elementy ciągów liczbowych, takie jak symbole waluty, separatory grup (lub tysięcy) i separatory dziesiętne, różnią się w zależności od kultury. Analizowanie metod niejawnie lub jawnie używa dostawcy formatu, który rozpoznaje te odmiany specyficzne dla kultury. Jeśli w wywołaniu Parse metody lub TryParse nie określono żadnego dostawcy formatu, jest używany dostawca formatu skojarzony z bieżącą NumberFormatInfo.CurrentInfo kulturą (NumberFormatInfoobiekt zwracany przez właściwość).

Dostawca formatu jest reprezentowany przez implementację IFormatProvider . Ten interfejs ma jeden element członkowski, metodę GetFormat , której pojedynczy parametr jest obiektem reprezentującym Type typ do sformatowania. Ta metoda zwraca obiekt, który udostępnia informacje o formatowaniu. Platforma .NET obsługuje następujące dwie IFormatProvider implementacje do analizowania ciągów liczbowych:

Poniższy przykład próbuje przekonwertować każdy ciąg w tablicy na Double wartość. Najpierw próbuje przeanalizować ciąg przy użyciu dostawcy formatu, który odzwierciedla konwencje kultury angielskiej (Stany Zjednoczone). Jeśli ta operacja zgłasza FormatExceptionwyjątek , próbuje przeanalizować ciąg przy użyciu dostawcy formatu, który odzwierciedla konwencje kultury francuskiej (Francji).

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("{0}: {1} --> {2}", culture.Name, value, number);
         }
         catch (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 (FormatException) {
               Console.WriteLine("{0}: Unable to parse '{1}'.",
                                 culture.Name, 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'.

Analiza składniowa i wartości NumberStyles

Elementy stylu (takie jak biały znak, separatory grup i separator dziesiętny), które mogą obsłużyć operacji analizowania, są definiowane przez NumberStyles wartość wyliczenia. Domyślnie ciągi reprezentujące wartości całkowite są analizowane przy użyciu NumberStyles.Integer wartości, która zezwala tylko na cyfry liczbowe, wiodące i końcowe białe znaki oraz znak wiodący. Ciągi reprezentujące wartości zmiennoprzecinkowe są analizowane przy użyciu kombinacji NumberStyles.Float wartości i NumberStyles.AllowThousands . Ten styl złożony zezwala na cyfry dziesiętne wraz z wiodącym i końcowym białym znakiem, znakiem wiodącym, separatorem dziesiętnym, separatorem grupy i wykładnikiem. Wywołując przeciążenie Parse metody lub TryParse zawierającej parametr typu NumberStyles i ustawiając co najmniej jedną NumberStyles flagę, można kontrolować elementy stylu, które mogą być obecne w ciągu dla operacji analizy, aby zakończyć się powodzeniem.

Na przykład ciąg zawierający separator grupy nie może zostać przekonwertowany na Int32 wartość przy użyciu Int32.Parse(String) metody . Jednak konwersja powiedzie się, jeśli używasz flagi NumberStyles.AllowThousands , jak pokazano w poniższym przykładzie.

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("{0} --> {1}", value, number);
      else
         Console.WriteLine("Unable to convert '{0}'", value);

      if (Int32.TryParse(value, NumberStyles.Integer | NumberStyles.AllowThousands,
                        provider, out number))
         Console.WriteLine("{0} --> {1}", value, number);
      else
         Console.WriteLine("Unable to convert '{0}'", 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

Ostrzeżenie

Operacja analizowania zawsze używa konwencji formatowania określonej kultury. Jeśli nie określisz kultury przez przekazanie CultureInfo obiektu lub NumberFormatInfo , zostanie użyta kultura skojarzona z bieżącym wątkiem.

W poniższej tabeli wymieniono elementy członkowskie NumberStyles wyliczenia i opisano wpływ, jaki mają na operację analizowania.

Wartość wyliczenia NumberStyles Wpływ na ciąg, który ma zostać przeanalizowany
NumberStyles.None Dozwolone są tylko cyfry liczbowe.
NumberStyles.AllowDecimalPoint Dozwolony jest separator dziesiętny i cyfry ułamkowe. W przypadku wartości całkowitych tylko zero jest dozwolone jako cyfra ułamkowa. Prawidłowe separatory dziesiętne są określane przez NumberFormatInfo.NumberDecimalSeparator właściwość or NumberFormatInfo.CurrencyDecimalSeparator .
NumberStyles.AllowExponent Znak "e" lub "E" może służyć do wskazywania notacji wykładniczej. Aby uzyskać więcej informacji, zobacz NumberStyles.
NumberStyles.AllowLeadingWhite Dozwolone jest wiodące odstępy.
NumberStyles.AllowTrailingWhite Dozwolony jest końcowy biały znak.
NumberStyles.AllowLeadingSign Znak dodatni lub ujemny może poprzedzać cyfry liczbowe.
NumberStyles.AllowTrailingSign Znak dodatni lub ujemny może podążać za cyframi liczbowymi.
NumberStyles.AllowParentheses Nawiasy mogą służyć do wskazywania wartości ujemnych.
NumberStyles.AllowThousands Separator grupy jest dozwolony. Znak separatora grupy jest określany przez NumberFormatInfo.NumberGroupSeparator właściwość or NumberFormatInfo.CurrencyGroupSeparator .
NumberStyles.AllowCurrencySymbol Symbol waluty jest dozwolony. Symbol waluty jest definiowany NumberFormatInfo.CurrencySymbol przez właściwość .
NumberStyles.AllowHexSpecifier Ciąg, który ma zostać przeanalizowany, jest interpretowany jako liczba szesnastkowa. Może zawierać cyfry szesnastkowe 0-9, A-F i a-f. Tej flagi można używać tylko do analizowania wartości całkowitych.

Ponadto NumberStyles wyliczenie zawiera następujące style złożone, które obejmują wiele NumberStyles flag.

Wartość Composite NumberStyles Obejmuje elementy członkowskie
NumberStyles.Integer NumberStyles.AllowLeadingWhiteZawiera style , NumberStyles.AllowTrailingWhitei NumberStyles.AllowLeadingSign . Jest to domyślny styl używany do analizowania wartości całkowitych.
NumberStyles.Number NumberStyles.AllowLeadingWhiteObejmuje style , , NumberStyles.AllowTrailingWhite, NumberStyles.AllowTrailingSignNumberStyles.AllowLeadingSign, NumberStyles.AllowDecimalPoint, i NumberStyles.AllowThousands .
NumberStyles.Float NumberStyles.AllowLeadingWhiteZawiera style , , NumberStyles.AllowLeadingSignNumberStyles.AllowTrailingWhite, NumberStyles.AllowDecimalPointi NumberStyles.AllowExponent .
NumberStyles.Currency Obejmuje wszystkie style z wyjątkiem NumberStyles.AllowExponent i NumberStyles.AllowHexSpecifier.
NumberStyles.Any Obejmuje wszystkie style z wyjątkiem NumberStyles.AllowHexSpecifier.
NumberStyles.HexNumber NumberStyles.AllowLeadingWhiteZawiera style , NumberStyles.AllowTrailingWhitei NumberStyles.AllowHexSpecifier .

Analiza składniowa i cyfry Unicode

Standard Unicode definiuje punkty kodu dla cyfr w różnych systemach pisania. Na przykład punkty kodu od U+0030 do U+0039 reprezentują podstawowe cyfry łacińskie od 0 do 9, punkty kodu od U+09E6 do U+09EF reprezentują cyfry Bangla od 0 do 9, a punkty kodu od U+FF10 do U+FF19 reprezentują cyfry pełne od 0 do 9. Jednak jedyne cyfry liczbowe rozpoznawane przez metody analizowania to podstawowe cyfry łacińskie 0–9 z punktami kodu z U+0030 do U+0039. Jeśli metoda analizowania liczbowego jest przekazywana ciąg zawierający inne cyfry, metoda zgłasza FormatExceptionwartość .

W poniższym przykładzie użyto Int32.Parse metody do analizowania ciągów składających się z cyfr w różnych systemach pisania. Jak pokazano w danych wyjściowych z przykładu, próba przeanalizowanie podstawowych cyfr łacińskich zakończy się powodzeniem, ale próba przeanalizowana cyfr Fullwidth, Arabski-Indic i Bangla kończy się niepowodzeniem.

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("'{0}' --> {1}", value, number);
      }
      catch (FormatException) {
         Console.WriteLine("Unable to parse '{0}'.", 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 '১২৩৪৫'.

Zobacz też