Przeczytaj w języku angielskim

Udostępnij za pośrednictwem


Struktura System.Char

Ten artykuł zawiera dodatkowe uwagi dotyczące dokumentacji referencyjnej dla tego interfejsu API.

Struktura Char reprezentuje punkty kodu Unicode przy użyciu kodowania UTF-16. Wartość obiektu Char jest jego 16-bitową wartością liczbową (porządkową).

Jeśli nie znasz formatu Unicode, wartości skalarnych, punktów kodu, par zastępczych, utF-16 i typu Rune, zobacz Wprowadzenie do kodowania znaków na platformie .NET.

W tym artykule analizowana jest relacja między obiektem Char a postacią oraz omawiane są niektóre typowe zadania wykonywane z użyciem instancji Char. Zalecamy rozważenie typu Rune wprowadzonego na platformie .NET Core 3.0 jako alternatywy dla Char wykonywania niektórych z tych zadań.

Obiekty char, znaki Unicode i ciągi

Obiekt String to sekwencyjny zbiór struktur Char reprezentujący ciąg tekstu. Większość znaków Unicode może być reprezentowana przez pojedynczy obiekt Char, ale znak zakodowany jako znak podstawowy, para zastępcza i/lub łączenie sekwencji znaków jest reprezentowany przez wiele obiektów Char. Z tego powodu struktura Char w obiekcie String nie musi być równoważna pojedynczemu znakowi Unicode.

Wiele 16-bitowych jednostek kodu służy do reprezentowania pojedynczych znaków Unicode w następujących przypadkach:

  • Glify, które mogą składać się z pojedynczego znaku lub znaku podstawowego, po którym następuje jeden lub więcej znaków łączących. Na przykład znak ä jest reprezentowany przez obiekt Char, którego jednostka kodu to U+0061, a następnie obiekt Char, którego jednostka kodu to U+0308. (Znak ä można również zdefiniować za pomocą pojedynczego obiektu Char, który ma jednostkę kodu U+00E4). Poniższy przykład ilustruje, że znak ä składa się z dwóch obiektów Char.

    using System;
    using System.IO;
    
    public class Example1
    {
        public static void Main()
        {
            StreamWriter sw = new StreamWriter("chars1.txt");
            char[] chars = { '\u0061', '\u0308' };
            string strng = new String(chars);
            sw.WriteLine(strng);
            sw.Close();
        }
    }
    // The example produces the following output:
    //       ä
    
  • Znaki poza podstawową płaszczyzną wielojęzyczną Unicode (BMP). Kod Unicode obsługuje szesnaście płaszczyzn oprócz protokołu BMP, który reprezentuje płaszczyznę 0. Punkt kodu Unicode jest reprezentowany w formacie UTF-32 przez wartość 21-bitową zawierającą płaszczyznę. Na przykład U+1D160 reprezentuje znak MUZYCZNY SYMBOL ÓSMEJ NUTY. Ponieważ kodowanie UTF-16 ma tylko 16 bitów, znaki poza BMP są reprezentowane przez pary zastępcze w formacie UTF-16. Poniższy przykład ilustruje, że odpowiednikiem UTF-32 dla U+1D160, znaku symbolu muzycznego ósmej nuty, jest U+D834 U+DD60. U+D834 jest wysokim surrogatem; wysokie surrogaty wahają się od U+D800 do U+DBFF. U+DD60 jest niskim surogatem; zakres niskich surogatów rozciąga się od U+DC00 do U+DFFF.

    using System;
    using System.IO;
    
    public class Example3
    {
        public static void Main()
        {
            StreamWriter sw = new StreamWriter(@".\chars2.txt");
            int utf32 = 0x1D160;
            string surrogate = Char.ConvertFromUtf32(utf32);
            sw.WriteLine("U+{0:X6} UTF-32 = {1} ({2}) UTF-16",
                         utf32, surrogate, ShowCodePoints(surrogate));
            sw.Close();
        }
    
        private static string ShowCodePoints(string value)
        {
            string retval = null;
            foreach (var ch in value)
                retval += String.Format("U+{0:X4} ", Convert.ToUInt16(ch));
    
            return retval.Trim();
        }
    }
    // The example produces the following output:
    //       U+01D160 UTF-32 = ð (U+D834 U+DD60) UTF-16
    

Znaki i kategorie znaków

Każdy znak Unicode lub prawidłowa para zastępcza należy do kategorii Unicode. Na platformie .NET kategorie Unicode są reprezentowane przez elementy członkowskie wyliczenia UnicodeCategory i zawierają na przykład wartości, takie jak UnicodeCategory.CurrencySymbol, UnicodeCategory.LowercaseLetteri UnicodeCategory.SpaceSeparator.

Aby określić kategorię Unicode znaku, wywołaj metodę GetUnicodeCategory. Na przykład następujący przykład wywołuje GetUnicodeCategory, aby wyświetlić kategorię Unicode każdego znaku w ciągu. Przykład działa poprawnie tylko wtedy, gdy w wystąpieniu String nie ma par zastępczych.

using System;
using System.Globalization;

class Example
{
   public static void Main()
   {
      // Define a string with a variety of character categories.
      String s = "The red car drove down the long, narrow, secluded road.";
      // Determine the category of each character.
      foreach (var ch in s)
         Console.WriteLine($"'{ch}': {Char.GetUnicodeCategory(ch)}");
   }
}
// The example displays the following output:
//      'T': UppercaseLetter
//      'h': LowercaseLetter
//      'e': LowercaseLetter
//      ' ': SpaceSeparator
//      'r': LowercaseLetter
//      'e': LowercaseLetter
//      'd': LowercaseLetter
//      ' ': SpaceSeparator
//      'c': LowercaseLetter
//      'a': LowercaseLetter
//      'r': LowercaseLetter
//      ' ': SpaceSeparator
//      'd': LowercaseLetter
//      'r': LowercaseLetter
//      'o': LowercaseLetter
//      'v': LowercaseLetter
//      'e': LowercaseLetter
//      ' ': SpaceSeparator
//      'd': LowercaseLetter
//      'o': LowercaseLetter
//      'w': LowercaseLetter
//      'n': LowercaseLetter
//      ' ': SpaceSeparator
//      't': LowercaseLetter
//      'h': LowercaseLetter
//      'e': LowercaseLetter
//      ' ': SpaceSeparator
//      'l': LowercaseLetter
//      'o': LowercaseLetter
//      'n': LowercaseLetter
//      'g': LowercaseLetter
//      ',': OtherPunctuation
//      ' ': SpaceSeparator
//      'n': LowercaseLetter
//      'a': LowercaseLetter
//      'r': LowercaseLetter
//      'r': LowercaseLetter
//      'o': LowercaseLetter
//      'w': LowercaseLetter
//      ',': OtherPunctuation
//      ' ': SpaceSeparator
//      's': LowercaseLetter
//      'e': LowercaseLetter
//      'c': LowercaseLetter
//      'l': LowercaseLetter
//      'u': LowercaseLetter
//      'd': LowercaseLetter
//      'e': LowercaseLetter
//      'd': LowercaseLetter
//      ' ': SpaceSeparator
//      'r': LowercaseLetter
//      'o': LowercaseLetter
//      'a': LowercaseLetter
//      'd': LowercaseLetter
//      '.': OtherPunctuation

Wewnętrznie w przypadku znaków spoza zakresu ASCII (od U+0000 do U+00FF) metoda GetUnicodeCategory zależy od kategorii Unicode zgłoszonych przez klasę CharUnicodeInfo. Począwszy od platformy .NET Framework 4.6.2, znaki Unicode są klasyfikowane na podstawie Standardu Unicode w wersji 8.0.0. W wersjach programu .NET Framework z programu .NET Framework 4 do .NET Framework 4.6.1 są one klasyfikowane na podstawie Standard Unicode w wersji 6.3.0.

Znaki i elementy tekstowe

Ponieważ pojedynczy znak może być reprezentowany przez wiele obiektów Char, pracowanie z poszczególnymi obiektami Char nie zawsze ma sens. Na przykład poniższy przykład konwertuje punkty kodu Unicode reprezentujące liczby Morza Egejskiego od 9 do 9 do zakodowanych jednostek kodu UTF-16. Ponieważ błędnie utożsamia obiekty Char ze znakami, błędnie zgłasza, że ciąg wynikowy ma 20 znaków.

using System;

public class Example5
{
    public static void Main()
    {
        string result = String.Empty;
        for (int ctr = 0x10107; ctr <= 0x10110; ctr++)  // Range of Aegean numbers.
            result += Char.ConvertFromUtf32(ctr);

        Console.WriteLine($"The string contains {result.Length} characters.");
    }
}
// The example displays the following output:
//     The string contains 20 characters.

Aby uniknąć założenia, że obiekt Char reprezentuje pojedynczy znak, można wykonać następujące czynności:

  • Możesz pracować z obiektem String w całości zamiast pracować z poszczególnymi znakami w celu reprezentowania i analizowania zawartości językowej.

  • Możesz użyć String.EnumerateRunes, jak pokazano w poniższym przykładzie:

    int CountLetters(string s)
    {
        int letterCount = 0;
    
        foreach (Rune rune in s.EnumerateRunes())
        {
            if (Rune.IsLetter(rune))
            { letterCount++; }
        }
    
        return letterCount;
    }
    
  • Możesz użyć klasy StringInfo do pracy z elementami tekstowymi zamiast pojedynczych obiektów Char. W poniższym przykładzie użyto obiektu StringInfo, aby zliczyć liczbę elementów tekstowych w ciągu składającym się z liczb morza egejskiego zero do dziewięciu. Ponieważ uważa ona parę zastępczą za pojedynczy znak, prawidłowo zgłasza, że ciąg zawiera dziesięć znaków.

    using System;
    using System.Globalization;
    
    public class Example4
    {
        public static void Main()
        {
            string result = String.Empty;
            for (int ctr = 0x10107; ctr <= 0x10110; ctr++)  // Range of Aegean numbers.
                result += Char.ConvertFromUtf32(ctr);
    
            StringInfo si = new StringInfo(result);
            Console.WriteLine($"The string contains {si.LengthInTextElements} characters.");
        }
    }
    // The example displays the following output:
    //       The string contains 10 characters.
    
  • Jeśli ciąg zawiera znak podstawowy, który ma co najmniej jeden znak łączący, możesz wywołać metodę String.Normalize, aby przekonwertować podciąg na pojedynczą jednostkę kodu zakodowanego w formacie UTF-16. Poniższy przykład wywołuje metodę String.Normalize, aby przekonwertować znak podstawowy U+0061 (MAŁA LITERA A) i połączyć znak U+0308 (POŁĄCZENIE DIAERESIS) do U+00E4 (MAŁA LITERA ŁACIŃSKA A Z DIAEREZĄ).

    using System;
    
    public class Example2
    {
        public static void Main()
        {
            string combining = "\u0061\u0308";
            ShowString(combining);
    
            string normalized = combining.Normalize();
            ShowString(normalized);
        }
    
        private static void ShowString(string s)
        {
            Console.Write("Length of string: {0} (", s.Length);
            for (int ctr = 0; ctr < s.Length; ctr++)
            {
                Console.Write("U+{0:X4}", Convert.ToUInt16(s[ctr]));
                if (ctr != s.Length - 1) Console.Write(" ");
            }
            Console.WriteLine(")\n");
        }
    }
    // The example displays the following output:
    //       Length of string: 2 (U+0061 U+0308)
    //
    //       Length of string: 1 (U+00E4)
    

Typowe operacje

Struktura Char udostępnia metody porównywania obiektów Char, konwertowania wartości bieżącego obiektu Char na obiekt innego typu i określania kategorii Unicode obiektu Char:

Aby to zrobić Użyj tych System.Char metod
Porównanie obiektów Char CompareTo i Equals
Konwertowanie punktu kodu na ciąg ConvertFromUtf32

Zobacz również typ Rune.
Konwertowanie obiektu Char lub pary zastępczej obiektów Char na punkt kodu Dla pojedynczego znaku: Convert.ToInt32(Char)

Dla pary zastępczej lub znaku w ciągu: Char.ConvertToUtf32

Zobacz również typ Rune.
Pobieranie kategorii Unicode znaku GetUnicodeCategory

Zobacz również Rune.GetUnicodeCategory.
Określanie, czy znak znajduje się w określonej kategorii Unicode, takiej jak cyfra, litera, znak interpunkcyjny, znak kontrolny itd. IsControl, IsDigit, IsHighSurrogate, IsLetter, IsLetterOrDigit, IsLower, IsLowSurrogate, IsNumber, IsPunctuation, IsSeparator, IsSurrogate, IsSurrogatePair, IsSymbol, IsUpperi IsWhiteSpace

Zobacz również analogiczne metody dla typu Rune.
Konwertowanie obiektu Char reprezentującego liczbę na typ wartości liczbowej GetNumericValue

Zobacz również Rune.GetNumericValue.
Konwertowanie znaku w ciągu na obiekt Char Parse i TryParse
Konwertowanie obiektu Char na obiekt String ToString
Zmień wielkość liter obiektu Char ToLower, ToLowerInvariant, ToUpperi ToUpperInvariant

Zobacz również odpowiednie metody dla typu Rune.

Wartości znaków i interoperacyjności

Gdy zarządzany typ Char, który jest reprezentowany jako jednostka kodu w formacie Unicode UTF-16, jest przekazywany do niezarządzanego kodu, marshaller interfejsu domyślnie konwertuje zestaw znaków na ANSI. Atrybut DllImportAttribute można zastosować do deklaracji wywoływania platformy, a atrybut StructLayoutAttribute do deklaracji międzyoperacyjnej COM, aby kontrolować, który zestaw znaków używa marshaled typu Char.