C#char中的Unicode SMP“字符”

时间:2013-05-10 15:48:39

标签: c# character-encoding astral-plane

我正在尝试确定字符编码对我正在计划的软件系统的影响,我在测试时发现了一些奇怪的东西。

据我所知,C#内部使用UTF-16(据我所知),它使用两个16位字段包含每个Unicode代码点。所以我想制作一些字符文字并故意选择和얤,因为前者来自SMP平面而后者来自BMP平面。结果是:

char ch1 = '얤'; // No problem
char ch2 = ''; // Compilation error "Too many characters in character literal"

发生了什么事?

这个问题的必然结果是,如果我有字符串“얤얤”,它会在MessageBox中正确显示,但是当我使用ToCharArray将其转换为char []时,我得到一个包含四个元素而不是三个元素的数组。此外,String.Length报告为四个而不是三个。

我在这里错过了什么吗?

2 个答案:

答案 0 :(得分:0)

您的源文件可能无法保存为UTF-8(在源代码中使用特殊字符时建议使用),因此编译器实际上可能会看到一个混淆它的字节序列。您可以通过在十六进制编辑器中打开源文件来验证 - 您将看到的字符代替您的角色可能会有所不同。

如果它尚未打开,您可以在工具 - >选项 - > Visual Studio中的文档(我使用2008)中启用该设置 - 选项为Save documents as Unicode when data cannot be saved in codepage

通常,最好使用字符序列指定特殊字符。

这个MSDN article描述了如何使用\uxxxx序列来指定所需的Unicode字符代码。这个blog entry列出了所有各种C#转义序列 - 我之所以包含它是因为它提到使用\ xnnn - 避免使用这种格式:它是\u的可变长度版本,它可能导致在某些情况下(不在你的情况下)的问题。

MSDN article指出字符分配不好的原因:所讨论字符的代码点是> FFFF超出了char类型的范围。

对于问题的字符串部分,答案是SMP字符表示为两个char值。 This SO question包含一些代码,显示如何从字符串中获取代码点,它涉及使用StringInfo.GetTextElementEnumerator

所有这些都包含在对这个答案的评论中,所以我刚刚将相关信息带入了这个答案,现在接受了。

答案 1 :(得分:0)

MSDN says that the char type can represent Unicode 16-bit character(因此只有字符形式为BMP)。

如果使用BMP外的字符(UTF-16:补充对 - 2x16位)编译器将其视为两个字符。