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

Lil*_*sey 122 c# internationalization

在C#中,ToUpper()和之间有什么区别ToUpperInvariant()

你能举例说明结果可能有所不同吗?

Jon*_*eet 143

ToUpper使用当前的文化.ToUpperInvariant使用不变的文化.

典型的例子是土耳其,其中"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);
    }
}
Run Code Online (Sandbox Code Playgroud)

欲了解更多关于土耳其,看到这个土耳其测试的博客文章.

我不会感到惊讶,因为有许多其他的大写字母问题围绕着被遗忘的角色等等.这只是我不知道的一个例子...部分原因是因为它多年前在Java中占据了我的位置,我在上层 - 使用字符串并将其与"MAIL"进行比较.这在土耳其没有那么好用......

  • 哈哈,我读到那个想法......"'土耳其'里面没有'我'字母" (44认同)
  • 快到 2019 年了,我让 Visual Studio 建议将“ımage”作为“Image”的字段名称,而 Unity 3D 向控制台发送内部错误“无法在“英语”Windows 上找到与“rıght”匹配的键名称”与土耳其区域设置的日期和时间。看起来有时连微软都未能通过土耳其测试,PC 的语言甚至不是土耳其语,哈哈。 (3认同)

Ter*_*ver 27

乔恩的回答很完美.我只想添加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 }, 
            }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

我也使用New Times Roman,因为它是一种更酷的字体.

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

我只是因为我喜欢紧凑(例如,不是生产)代码而减少了一些其他行.

我此刻真的没有更好的事情要做.

  • "乔恩的回答很完美." 谈论冗余的陈述.;) (5认同)

Caf*_*eek 15

从MSDN开始

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

ToUpperInvariant方法等同于ToUpper(CultureInfo.InvariantCulture)

仅仅因为资本i是英语中的"我",并不总是如此.


krz*_*chu 9

String.ToUpper并且String.ToLower可以根据不同的文化给出不同的结果 最着名的例子是土耳其语例子,将小写拉丁语"i"转换为大写,不会导致大写拉丁语"I",而是土耳其语"I".

I的大写取决于文化,上排 - 小写字母,下排 - 大写字母

至于我,即使使用上面的图片(源代码)也是令人困惑的,我写了一个程序(参见下面的源代码)来查看土耳其语示例的确切输出:

# 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)
Run Code Online (Sandbox Code Playgroud)

如你看到的:

  1. 大写小写字母和小写大写字母对于不变文化和土耳其文化给出不同的结果.
  2. 无论文化是什么,大写字母大写字母和小写字母小写字母都没有效果.
  3. Culture.CultureInvariant 保留土耳其字符
  4. 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})";
        }
    }
}
Run Code Online (Sandbox Code Playgroud)