大写字符串的长度是否始终与原始字符串相同?

  • 无论使用何种文化,unicode大写字符串的长度是否始终与原始字符串的长度相同?

  • 无论使用何种文化,unicode小写字符串的长度是否始终与原始字符串的长度相同?

换句话说,C#中的以下是真的吗?

text.ToUpper(CultureInfo.CurrentCulture).Length == text.Length text.ToLower(CultureInfo.CurrentCulture).Length == text.Length 

请注意,我对字节数不感兴趣: 关于它的问题已经得到解答。

我可以给出部分答案。 对于长度为2的所有字符串(其中大约有40亿),对于德国文化( de-DE ),您的断言包含:

  static unsafe void TestUnicodeLength2() { Parallel.For(char.MinValue, char.MaxValue + 1, charVal => { var firstChar = checked((char)charVal); var buffer = new string(firstChar, 2); fixed (char* bufferPtr = buffer) { var currentCulture = CultureInfo.CurrentCulture; for (int i = char.MinValue; i <= char.MaxValue; i++) { bufferPtr[1] = checked((char)i); var toLower = buffer.ToLower(currentCulture); if (toLower.Length != buffer.Length) { Console.WriteLine(buffer + " => " + toLower); Debugger.Break(); } var toUpper = buffer.ToUpper(currentCulture); if (toUpper.Length != buffer.Length) { Console.WriteLine(buffer + " => " + toUpper); Debugger.Break(); } } } }); } 

这运行大约2分钟。

我认为这是一个相当强有力的证据,断言总是成立,因为通过测试两个字符的所有可能组合,我们自动测试存在的所有代码点和所有没有人会想到的奇怪组合。

更新:我后来对随机字符串(每个256个字符长度)进行了类似的测试,总长度为2560亿个字符。 断言仍然有效。

就Unicode标准而言,问题的答案是“否”和“是”。

例如,当转换为大写时,“ß”U + 00DF LATIN SMALL LETTER SHARP S通过Unicode映射规则映射到两个字符“SS”。 可以将它映射到单个字符“ẞ”U + 1E9E LATIN CAPITAL LETTER SHARP S,但这不是默认值(并且根本不常见)。 另一个例子是“fi”U + FB01 LATIN SMALL LIGATURE FI被映射到“FI”。

在相反的方向上,没有可以改变字符数的默认映射。 请参阅字符属性,案例映射和名称常见问题解答 ,它链接到文件SpecialCasing.txt ,其中包含与简单一对一映射的所有偏差。 那里使小写字符串与大写原文不同的唯一规则是与立陶宛语实践相关的一些可选规则。

目前,这是事实。 .NET开发人员决定使用Windows API for Unicode,而那些不支持更改字符串长度的大小写转换。

但是,.NET团队并不保证它始终如此。 如果Windows获得支持这些转换的新API,则可能会更新.NET以使用它们。

请参阅System.String.ToUpper()不遵循 Microsoft Connect上的UNICODE SpecialCasing 。