System.Char 结构
本文提供了此 API 参考文档的补充说明。
该 Char 结构使用 UTF-16 编码表示 Unicode 码位。 对象的值 Char 是它的 16 位数字(序号)值。
如果不熟悉 Unicode、标量值、码位、代理项对、UTF-16 和 Rune 类型,请参阅 .NET 中的字符编码简介。
本文探讨对象与字符之间的关系 Char ,并讨论使用 Char 实例执行的一些常见任务。 建议考虑 . Rune NET Core 3.0 中引入的类型,作为执行其中一些任务的替代方法 Char 。
Char 对象、Unicode 字符和字符串
对象 String 是表示文本字符串的结构的顺序集合 Char 。 大多数 Unicode 字符都可以由单个 Char 对象表示,但编码为基字符、代理项对和/或组合字符序列的字符由多个 Char 对象表示。 因此, Char 对象中的 String 结构不一定等效于单个 Unicode 字符。
在以下情况下,多个 16 位代码单元用于表示单个 Unicode 字符:
字形,它可能包含单个字符或基字符,后跟一个或多个组合字符。 例如,字符 ä 由 Char 代码单元为 U+0061 的对象表示,后跟 Char 代码单元为 U+0308 的对象。 (字符 ä 也可以由具有 U+00E4 代码单元的单个 Char 对象定义。下面的示例演示字符 ä 由两 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: // ä
open System open System.IO let sw = new StreamWriter("chars1.txt") let chars = [| '\u0061'; '\u0308' |] let string = String chars sw.WriteLine string sw.Close() // The example produces the following output: // ä
Imports System.IO Module Example2 Public Sub Main() Dim sw As New StreamWriter("chars1.txt") Dim chars() As Char = {ChrW(&H61), ChrW(&H308)} Dim strng As New String(chars) sw.WriteLine(strng) sw.Close() End Sub End Module ' The example produces the following output: ' ä
Unicode 基本多语言平面外部的字符(BMP)。 除表示平面 0 的 BMP 之外,Unicode 还支持 16 个平面。 Unicode 代码点由包含平面的 21 位值在 UTF-32 中表示。 例如,U+1D160 表示音乐符号第八注字符。 由于 UTF-16 编码只有 16 位,因此 BMP 之外的字符由 UTF-16 中的代理项对表示。 以下示例演示 U+1D160 的 UTF-32 等效项(音乐符号第八音符)为 U+D834 U+DD60。 U+D834 是高代理项;高代理项范围从 U+D800 到 U+DBFF。 U+DD60 是低代理项;低代理项范围从 U+DC00 到 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
open System open System.IO let showCodePoints (value: char seq) = let str = value |> Seq.map (fun ch -> $"U+{Convert.ToUInt16 ch:X4}") |> String.concat "" str.Trim() let sw = new StreamWriter(@".\chars2.txt") let utf32 = 0x1D160 let surrogate = Char.ConvertFromUtf32 utf32 sw.WriteLine $"U+{utf32:X6} UTF-32 = {surrogate} ({showCodePoints surrogate}) UTF-16" sw.Close() // The example produces the following output: // U+01D160 UTF-32 = ð (U+D834 U+DD60) UTF-16
Imports System.IO Module Example4 Public Sub Main() Dim sw As New StreamWriter(".\chars2.txt") Dim utf32 As Integer = &H1D160 Dim surrogate As String = Char.ConvertFromUtf32(utf32) sw.WriteLine("U+{0:X6} UTF-32 = {1} ({2}) UTF-16", utf32, surrogate, ShowCodePoints(surrogate)) sw.Close() End Sub Private Function ShowCodePoints(value As String) As String Dim retval As String = Nothing For Each ch In value retval += String.Format("U+{0:X4} ", Convert.ToUInt16(ch)) Next Return retval.Trim() End Function End Module ' The example produces the following output: ' U+01D160 UTF-32 = ð (U+D834 U+DD60) UTF-16
字符和字符类别
每个 Unicode 字符或有效的代理项对都属于 Unicode 类别。 在 .NET 中,Unicode 类别由枚举的成员 UnicodeCategory 表示,并包括值,例如 UnicodeCategory.CurrencySymbol, UnicodeCategory.LowercaseLetter以及 UnicodeCategory.SpaceSeparator。
若要确定字符的 Unicode 类别,请调用 GetUnicodeCategory 该方法。 例如,以下示例调用 GetUnicodeCategory 显示字符串中每个字符的 Unicode 类别。 仅当实例中 String 没有代理项对时,该示例才能正常工作。
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("'{0}': {1}", 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
open System
// Define a string with a variety of character categories.
let s = "The red car drove down the long, narrow, secluded road."
// Determine the category of each character.
for ch in s do
printfn $"'{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
Imports System.Globalization
Module Example1
Public Sub Main()
' Define a string with a variety of character categories.
Dim s As String = "The car drove down the narrow, secluded road."
' Determine the category of each character.
For Each ch In s
Console.WriteLine("'{0}': {1}", ch, Char.GetUnicodeCategory(ch))
Next
End Sub
End Module
' 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
在内部,对于 ASCII 范围之外的字符(U+0000 到 U+00FF),该方法 GetUnicodeCategory 取决于类报告的 CharUnicodeInfo Unicode 类别。 从 .NET Framework 4.6.2 开始,Unicode 字符基于 Unicode 标准版本 8.0.0 进行分类。 在 .NET Framework 4 到 .NET Framework 4.6.1 的 .NET Framework 版本中,它们基于 Unicode 标准版本 6.3.0 进行分类。
字符和文本元素
由于单个字符可以由多个 Char 对象表示,因此处理单个 Char 对象并不总是有意义的。 例如,以下示例将表示爱琴海数字零到 9 的 Unicode 码位转换为 UTF-16 编码的代码单元。 因为它错误地将 Char 对象与字符相等,因此它不准确地报告生成的字符串有 20 个字符。
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 {0} characters.", result.Length);
}
}
// The example displays the following output:
// The string contains 20 characters.
open System
let result =
[ for i in 0x10107..0x10110 do // Range of Aegean numbers.
Char.ConvertFromUtf32 i ]
|> String.concat ""
printfn $"The string contains {result.Length} characters."
// The example displays the following output:
// The string contains 20 characters.
Module Example5
Public Sub Main()
Dim result As String = String.Empty
For ctr As Integer = &H10107 To &H10110 ' Range of Aegean numbers.
result += Char.ConvertFromUtf32(ctr)
Next
Console.WriteLine("The string contains {0} characters.", result.Length)
End Sub
End Module
' The example displays the following output:
' The string contains 20 characters.
可以执行以下操作以避免假设对象 Char 表示单个字符:
可以使用 String 整个对象,而不是使用其单个字符来表示和分析语言内容。
如 String.EnumerateRunes 以下示例所示:
int CountLetters(string s) { int letterCount = 0; foreach (Rune rune in s.EnumerateRunes()) { if (Rune.IsLetter(rune)) { letterCount++; } } return letterCount; }
let countLetters (s: string) = let mutable letterCount = 0 for rune in s.EnumerateRunes() do if Rune.IsLetter rune then letterCount <- letterCount + 1 letterCount
可以使用 StringInfo 该类来处理文本元素,而不是单个 Char 对象。 以下示例使用 StringInfo 对象计算由爱琴海数字零到 9 组成的字符串中的文本元素数。 因为它认为代理项对是单个字符,所以它正确地报告该字符串包含 10 个字符。
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 {0} characters.", si.LengthInTextElements); } } // The example displays the following output: // The string contains 10 characters.
open System open System.Globalization let result = [ for i in 0x10107..0x10110 do // Range of Aegean numbers. Char.ConvertFromUtf32 i ] |> String.concat "" let si = StringInfo result printfn $"The string contains {si.LengthInTextElements} characters." // The example displays the following output: // The string contains 10 characters.
Imports System.Globalization Module Example6 Public Sub Main() Dim result As String = String.Empty For ctr As Integer = &H10107 To &H10110 ' Range of Aegean numbers. result += Char.ConvertFromUtf32(ctr) Next Dim si As New StringInfo(result) Console.WriteLine("The string contains {0} characters.", si.LengthInTextElements) End Sub End Module ' The example displays the following output: ' The string contains 10 characters.
如果字符串包含具有一个或多个组合字符的基字符,则可以调用 String.Normalize 方法将子字符串转换为单个 UTF-16 编码的代码单元。 下面的示例调用 String.Normalize 该方法将基字符 U+0061(拉丁文 SMALL LETTER A)和组合字符 U+0308(COMBINING DIAERESIS)转换为 U+00E4(拉丁文小写字母 A WITH 分音)。
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)
open System let showString (s: string) = printf $"Length of string: {s.Length} (" for i = 0 to s.Length - 1 do printf $"U+{Convert.ToUInt16 s[i]:X4}" if i <> s.Length - 1 then printf " " printfn ")\n" let combining = "\u0061\u0308" showString combining let normalized = combining.Normalize() showString normalized // The example displays the following output: // Length of string: 2 (U+0061 U+0308) // // Length of string: 1 (U+00E4)
Module Example3 Public Sub Main() Dim combining As String = ChrW(&H61) + ChrW(&H308) ShowString(combining) Dim normalized As String = combining.Normalize() ShowString(normalized) End Sub Private Sub ShowString(s As String) Console.Write("Length of string: {0} (", s.Length) For ctr As Integer = 0 To s.Length - 1 Console.Write("U+{0:X4}", Convert.ToUInt16(s(ctr))) If ctr <> s.Length - 1 Then Console.Write(" ") Next Console.WriteLine(")") Console.WriteLine() End Sub End Module ' The example displays the following output: ' Length of string: 2 (U+0061 U+0308) ' ' Length of string: 1 (U+00E4)
常见操作
该 Char 结构提供比较 Char 对象的方法,将当前 Char 对象的值转换为另一种类型的对象,并确定对象的 Unicode 类别 Char :
要执行此操作 | 使用这些 System.Char 方法 |
---|---|
比较 Char 对象 | CompareTo 和 Equals |
将代码点转换为字符串 | ConvertFromUtf32 另请参阅类型 Rune 。 |
将 Char 对象或代理项对 Char 转换为代码点 | 对于单个字符: Convert.ToInt32(Char) 对于代理项对或字符串中的字符: Char.ConvertToUtf32 另请参阅类型 Rune 。 |
获取字符的 Unicode 类别 | GetUnicodeCategory 另请参阅 Rune.GetUnicodeCategory。 |
确定字符是否位于特定的 Unicode 类别中,例如数字、字母、标点符号、控制字符等 | IsControl、IsDigit、、IsLetterIsHighSurrogate、、 IsLowerIsLetterOrDigitIsUpperIsSymbolIsSurrogateIsPunctuationIsSurrogatePairIsLowSurrogateIsNumberIsSeparator和IsWhiteSpace 另请参阅有关 Rune 该类型的相应方法。 |
将 Char 表示数字的对象转换为数值类型 | GetNumericValue 另请参阅 Rune.GetNumericValue。 |
将字符串中的字符转换为 Char 对象 | Parse 和 TryParse |
将 Char 对象转换为 String 对象 | ToString |
更改对象的大小写Char | ToLower、ToLowerInvariant、ToUpper 和 ToUpperInvariant 另请参阅有关 Rune 该类型的相应方法。 |
字符值和互操作
当托管 Char 类型(表示为 Unicode UTF-16 编码的代码单元)传递到非托管代码时,互操作封送器默认将字符集转换为 ANSI。 可以将属性 DllImportAttribute 应用于平台调用声明,并将 StructLayoutAttribute 属性应用于 COM 互操作声明,以控制封送 Char 类型使用的字符集。
反馈
https://aka.ms/ContentUserFeedback。
即将发布:在整个 2024 年,我们将逐步淘汰作为内容反馈机制的“GitHub 问题”,并将其取代为新的反馈系统。 有关详细信息,请参阅:提交和查看相关反馈