转:https://www.mgenware.com/blog/?p=2202
.NET中字符串类型的Unicode的编码是UTF16,所以foreach枚举字符串可能会枚举到两个Unicode Surrogate值。为了枚举字符串中每个完整的Unicode字符值,写个小方法。很简单,通过Char.IsSurrogate判断是否是Unicode Surrogate,然后通过Char.ConvertToUtf32方法把两个Surrogate值转换成一个完整的int代表完整的Unicode编码值。
如下代码:
static IEnumerable<int> EnumerateCharValues(string str)
{
int i = 0;
while (i < str.Length)
{
var c = str[i];
if (Char.IsSurrogate(c) && i != str.Length - 1)
{
i += 2;
yield return Char.ConvertToUtf32(c, str[i - 1]);
}
else
{
i++;
yield return c;
}
}
}
测试:
//创建一对Surrogate
var surrogatePair = Char.ConvertFromUtf32(0x1F600);
//构造一个测试字符串
var str = "a" + surrogatePair + "b" + surrogatePair;
Console.WriteLine("Length: {0}", str.Length);
foreach (var i in EnumerateCharValues(str))
Console.WriteLine("U+{0:X}", i);
输出:
Length: 6
U+61
U+1F600
U+62
U+1F600
OK,虽然String长度为6,但是因为有2对Surrogate,所以总共只有4个字符。