【问题标题】:In C# what is the difference between ToUpper() and ToUpperInvariant()?在 C# 中,ToUpper() 和 ToUpperInvariant() 有什么区别?
【发布时间】:2011-04-02 18:54:54
【问题描述】:

在 C# 中,ToUpper()ToUpperInvariant() 有什么区别?

您能举一个结果可能不同的例子吗?

【问题讨论】:

  • [组织] 这个问题应该有标签“国际化”吗?

标签: c# internationalization


【解决方案1】:

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”进行比较。这在土耳其并不奏效......

【讨论】:

  • 哈哈我读到这个想法......“'土耳其'里面没有字母'i'”
  • 快到 2019 年了,我让 Visual Studio 建议 ımage 作为 Image 的字段名称,并且 Unity 3D 在“英语”Windows 上向控制台 Unable to find key name that matches 'rıght' 发送内部错误日期和时间的土耳其区域设置。看起来有时连微软都没有通过土耳其测试,PC 的语言甚至都不是土耳其语,只是哈哈。
【解决方案2】:

从 MSDN 开始

http://msdn.microsoft.com/en-us/library/system.string.toupperinvariant.aspx

ToUpperInvariant 方法是 相当于 ToUpper(CultureInfo.InvariantCulture)

仅仅因为大写 i 在英文中是 'I',并不总是如此。

【讨论】:

    【解决方案3】:

    ToUpperInvariant 使用来自invariant culture 的规则

    【讨论】:

      【解决方案4】:

      英文没有区别。只有在土耳其文化中才能发现差异。

      【讨论】:

      • 您确定土耳其语是世界上唯一一种对大写字母的规则与英语不同的文化吗?我觉得这很难相信。
      • 土耳其语是最常用的例子,但不是唯一的例子。是语言,而不是文化,有四种不同的我。不过,土耳其语 +1。
      • 肯定还有其他的。无论如何,大多数人在编程中永远不会遇到这些语言
      • 当然会的。 Web 应用程序向全球开放,最好设置参数。如果您在不使用 unicode 的遗留数据库上进行操作怎么办?您将接受哪些字符作为用户名?如果您必须将客户名称输入到基于 COBOL 构建的旧版 ERP 中怎么办?很多情况下,文化很重要。更不用说日期和数字了。 4.54 用某些语言写成 4,54。从长远来看,假装那些其他语言不存在不会让你走得太远。
      • 显然文化对于日期和数字很重要,我只是告诉大多数人永远不会遇到在 toUpper 和 toUpperInvariant 中具有不同结果的语言。
      【解决方案5】:

      乔恩的回答是完美的。我只是想补充一点,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,因为它是一种更酷的字体。

      我还设置了FormFont 属性而不是两个Label 控件,因为Font 属性是继承的。

      我减少了其他几行代码,只是因为我喜欢紧凑(示例,而不是生产)代码。

      我真的没有什么比这更好的了。

      【讨论】:

      【解决方案6】:

      String.ToUpperString.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)
      

      如你所见:

      1. 大写小写字母和小写大写字母对于不变文化和土耳其文化给出不同的结果。
      2. 无论文化是什么,大写大写字母和小写小写字母都不起作用。
      3. Culture.CultureInvariant 保留土耳其字符原样
      4. ToUpperToLower 是可逆的,即在大写字符后将其小写,使其恢复为原始形式,只要两个操作使用相同的文化。

      根据MSDN,对于Char.ToUpperChar.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})";
              }
          }
      }
      

      【讨论】:

      • 案例表很有帮助。谢谢!
      • 我会明确地说这是微软的完全错误设计。如果我将英文“i”设为大写,则英文“I”应该总是出现。如果我将土耳其语“ı”设为大写,则应该出现土耳其语“İ”。其他任何事情都没有意义,并且会产生很多问题。当我有一个 100% 的英文文本并将其设为大写时,应该总是有一个英文文本出来,里面没有任何土耳其字母。我无法理解微软是如何犯下如此大的设计错误的。
      猜你喜欢
      • 2011-04-05
      • 2014-03-01
      • 1970-01-01
      • 2010-10-01
      • 2010-11-18
      • 2011-02-13
      • 1970-01-01
      • 1970-01-01
      • 2011-10-18
      相关资源
      最近更新 更多