【发布时间】:2011-04-02 18:54:54
【问题描述】:
在 C# 中,ToUpper() 和 ToUpperInvariant() 有什么区别?
您能举一个结果可能不同的例子吗?
【问题讨论】:
-
[组织] 这个问题应该有标签“国际化”吗?
在 C# 中,ToUpper() 和 ToUpperInvariant() 有什么区别?
您能举一个结果可能不同的例子吗?
【问题讨论】:
ToUpper 使用当前文化。 ToUpperInvariant 使用不变的文化。
典型的例子是土耳其,其中“i”的大写不是“I”。
显示差异的示例代码:
using System;
using System.Drawing;
using System.Globalization;
using System.Threading;
using System.Windows.Forms;
public class Test
{
[STAThread]
static void Main()
{
string invariant = "iii".ToUpperInvariant();
CultureInfo turkey = new CultureInfo("tr-TR");
Thread.CurrentThread.CurrentCulture = turkey;
string cultured = "iii".ToUpper();
Font bigFont = new Font("Arial", 40);
Form f = new Form {
Controls = {
new Label { Text = invariant, Location = new Point(20, 20),
Font = bigFont, AutoSize = true},
new Label { Text = cultured, Location = new Point(20, 100),
Font = bigFont, AutoSize = true }
}
};
Application.Run(f);
}
}
有关土耳其语的更多信息,请参阅Turkey Test blog post。
听到关于省略字符等还有各种其他大写问题,我不会感到惊讶。这只是我知道的一个例子......部分原因是它在几年前在 Java 中咬了我,在哪里我将字符串大写并将其与“MAIL”进行比较。这在土耳其并不奏效......
【讨论】:
ımage 作为 Image 的字段名称,并且 Unity 3D 在“英语”Windows 上向控制台 Unable to find key name that matches 'rıght' 发送内部错误日期和时间的土耳其区域设置。看起来有时连微软都没有通过土耳其测试,PC 的语言甚至都不是土耳其语,只是哈哈。
从 MSDN 开始
http://msdn.microsoft.com/en-us/library/system.string.toupperinvariant.aspx
ToUpperInvariant 方法是 相当于 ToUpper(CultureInfo.InvariantCulture)
仅仅因为大写 i 在英文中是 'I',并不总是如此。
【讨论】:
ToUpperInvariant 使用来自invariant culture 的规则
【讨论】:
英文没有区别。只有在土耳其文化中才能发现差异。
【讨论】:
乔恩的回答是完美的。我只是想补充一点,ToUpperInvariant 与调用ToUpper(CultureInfo.InvariantCulture) 相同。
这让 Jon 的示例更简单:
using System;
using System.Drawing;
using System.Globalization;
using System.Threading;
using System.Windows.Forms;
public class Test
{
[STAThread]
static void Main()
{
string invariant = "iii".ToUpper(CultureInfo.InvariantCulture);
string cultured = "iii".ToUpper(new CultureInfo("tr-TR"));
Application.Run(new Form {
Font = new Font("Times New Roman", 40),
Controls = {
new Label { Text = invariant, Location = new Point(20, 20), AutoSize = true },
new Label { Text = cultured, Location = new Point(20, 100), AutoSize = true },
}
});
}
}
我还使用了 New Times Roman,因为它是一种更酷的字体。
我还设置了Form 的Font 属性而不是两个Label 控件,因为Font 属性是继承的。
我减少了其他几行代码,只是因为我喜欢紧凑(示例,而不是生产)代码。
我真的没有什么比这更好的了。
【讨论】:
String.ToUpper 和 String.ToLower 在不同的文化中可以给出不同的结果。最著名的例子是the Turkish example,将小写拉丁字母“i”转换为大写字母不会导致大写拉丁字母“I”,而是土耳其语“I”。
对我来说,即使上面的图片 (source) 也让我感到困惑,我编写了一个程序(参见下面的源代码)来查看土耳其示例的确切输出:
# Lowercase letters
Character | UpperInvariant | UpperTurkish | LowerInvariant | LowerTurkish
English i - i (\u0069) | I (\u0049) | I (\u0130) | i (\u0069) | i (\u0069)
Turkish i - ı (\u0131) | ı (\u0131) | I (\u0049) | ı (\u0131) | ı (\u0131)
# Uppercase letters
Character | UpperInvariant | UpperTurkish | LowerInvariant | LowerTurkish
English i - I (\u0049) | I (\u0049) | I (\u0049) | i (\u0069) | ı (\u0131)
Turkish i - I (\u0130) | I (\u0130) | I (\u0130) | I (\u0130) | i (\u0069)
如你所见:
Culture.CultureInvariant 保留土耳其字符原样ToUpper 和 ToLower 是可逆的,即在大写字符后将其小写,使其恢复为原始形式,只要两个操作使用相同的文化。根据MSDN,对于Char.ToUpper 和Char.ToLower,土耳其语和阿塞拜疆语是唯一受影响的文化,因为它们是唯一具有单字符大小写差异的文化。对于字符串,可能会受到更多文化的影响。
用于生成输出的控制台应用程序源代码:
using System;
using System.Globalization;
using System.Linq;
using System.Text;
namespace TurkishI
{
class Program
{
static void Main(string[] args)
{
var englishI = new UnicodeCharacter('\u0069', "English i");
var turkishI = new UnicodeCharacter('\u0131', "Turkish i");
Console.WriteLine("# Lowercase letters");
Console.WriteLine("Character | UpperInvariant | UpperTurkish | LowerInvariant | LowerTurkish");
WriteUpperToConsole(englishI);
WriteLowerToConsole(turkishI);
Console.WriteLine("\n# Uppercase letters");
var uppercaseEnglishI = new UnicodeCharacter('\u0049', "English i");
var uppercaseTurkishI = new UnicodeCharacter('\u0130', "Turkish i");
Console.WriteLine("Character | UpperInvariant | UpperTurkish | LowerInvariant | LowerTurkish");
WriteLowerToConsole(uppercaseEnglishI);
WriteLowerToConsole(uppercaseTurkishI);
Console.ReadKey();
}
static void WriteUpperToConsole(UnicodeCharacter character)
{
Console.WriteLine("{0,-9} - {1,10} | {2,-14} | {3,-12} | {4,-14} | {5,-12}",
character.Description,
character,
character.UpperInvariant,
character.UpperTurkish,
character.LowerInvariant,
character.LowerTurkish
);
}
static void WriteLowerToConsole(UnicodeCharacter character)
{
Console.WriteLine("{0,-9} - {1,10} | {2,-14} | {3,-12} | {4,-14} | {5,-12}",
character.Description,
character,
character.UpperInvariant,
character.UpperTurkish,
character.LowerInvariant,
character.LowerTurkish
);
}
}
class UnicodeCharacter
{
public static readonly CultureInfo TurkishCulture = new CultureInfo("tr-TR");
public char Character { get; }
public string Description { get; }
public UnicodeCharacter(char character) : this(character, string.Empty) { }
public UnicodeCharacter(char character, string description)
{
if (description == null) {
throw new ArgumentNullException(nameof(description));
}
Character = character;
Description = description;
}
public string EscapeSequence => ToUnicodeEscapeSequence(Character);
public UnicodeCharacter LowerInvariant => new UnicodeCharacter(Char.ToLowerInvariant(Character));
public UnicodeCharacter UpperInvariant => new UnicodeCharacter(Char.ToUpperInvariant(Character));
public UnicodeCharacter LowerTurkish => new UnicodeCharacter(Char.ToLower(Character, TurkishCulture));
public UnicodeCharacter UpperTurkish => new UnicodeCharacter(Char.ToUpper(Character, TurkishCulture));
private static string ToUnicodeEscapeSequence(char character)
{
var bytes = Encoding.Unicode.GetBytes(new[] {character});
var prefix = bytes.Length == 4 ? @"\U" : @"\u";
var hex = BitConverter.ToString(bytes.Reverse().ToArray()).Replace("-", string.Empty);
return $"{prefix}{hex}";
}
public override string ToString()
{
return $"{Character} ({EscapeSequence})";
}
}
}
【讨论】: