Dalam C # apa perbedaan antara ToUpper () dan ToUpperInvariant ()?

133

Dalam C #, apa perbedaan antara ToUpper()dan ToUpperInvariant()?

Bisakah Anda memberi contoh di mana hasilnya mungkin berbeda?

Lill Lansey
sumber
3
[Organisasi] Haruskah pertanyaan ini memiliki tag "internasionalisasi"?
jasso

Jawaban:

154

ToUppermenggunakan budaya saat ini. ToUpperInvariantmenggunakan budaya invarian.

Contoh kanonik adalah Turki, di mana huruf "i" bukan "aku".

Kode sampel menunjukkan perbedaan:

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);
    }
}

Untuk lebih lanjut tentang bahasa Turki, lihat posting blog Tes Turki ini .

Saya tidak akan terkejut mendengar bahwa ada berbagai masalah kapitalisasi lain di sekitar karakter yang dihapus dll -menarik string dan membandingkannya dengan "MAIL". Itu tidak bekerja dengan baik di Turki ...

Jon Skeet
sumber
45
haha saya membaca pemikiran itu ... "'Turki' tidak memiliki huruf 'i' di dalamnya"
Jeff Mercado
Ini hampir 2019 dan saya memiliki Visual Studio menyarankan ımagesebagai nama bidang untuk Imagedan Unity 3D spamming kesalahan internal ke konsol Unable to find key name that matches 'rıght'pada Windows "Inggris" dengan pengaturan regional Turki untuk tanggal dan waktu. Sepertinya kadang-kadang bahkan Microsoft gagal dalam tes Turki, bahasa PC bahkan bukan Turki, hanya lol.
Guney Ozsan
28

Jawaban Jon sempurna. Saya hanya ingin menambahkan itu ToUpperInvariantsama dengan menelepon ToUpper(CultureInfo.InvariantCulture).

Itu membuat contoh Jon sedikit lebih sederhana:

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 }, 
            }
        });
    }
}

Saya juga menggunakan New Times Roman karena ini adalah font yang lebih keren.

Saya juga mengatur Form's Fontproperti bukannya dua Labelkontrol karena Fontproperti diwariskan.

Dan saya mengurangi beberapa baris lain hanya karena saya suka kode kompak (misalnya, bukan produksi).

Saya benar-benar tidak memiliki hal yang lebih baik untuk dilakukan saat ini.

Tergiver
sumber
5
"Jawaban Jon sempurna." Bicara tentang pernyataan yang berlebihan. ;)
krillgar
1
Metode ToUpper tidak memiliki kelebihan parameter untuk saya? apakah versi yang lebih lama miliki? Saya tidak mengerti
batmaci
Saya tidak tahu, ini didokumentasikan di sini: msdn.microsoft.com/en-us/library/system.string.toupper.aspx
Tergiver
12

String.ToUpperdan String.ToLowerdapat memberikan hasil yang berbeda mengingat budaya yang berbeda. Contoh yang paling dikenal adalah contoh Turki , yang mengubah huruf latin "i" menjadi huruf kapital, tidak menghasilkan huruf latin "I", tetapi dalam bahasa Turki "I".

Kapitalisasi huruf I tergantung pada budaya, baris atas - huruf kecil, baris bawah - huruf besar

Bagi saya itu membingungkan bahkan dengan gambar di atas ( sumber ), saya menulis sebuah program (lihat kode sumber di bawah) untuk melihat output yang tepat untuk contoh Turki:

# 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)

Seperti yang Anda lihat:

  1. Huruf kecil huruf besar dan huruf kecil memberikan hasil yang berbeda untuk budaya invarian dan budaya Turki.
  2. Huruf besar huruf kecil dan huruf kecil tidak berpengaruh, tidak peduli apa budaya itu.
  3. Culture.CultureInvariant meninggalkan karakter Turki apa adanya
  4. ToUpperdan ToLowerbersifat reversibel, yaitu menurunkan karakter setelah menaikkannya, membawanya ke bentuk asli, selama kedua operasi budaya yang sama digunakan.

Menurut MSDN , untuk Char.ToUpper dan Char.ToLower Turki dan Azeri adalah satu-satunya budaya yang terpengaruh karena mereka adalah satu-satunya dengan perbedaan casing karakter tunggal. Untuk string, mungkin ada lebih banyak budaya yang terpengaruh.


Kode sumber aplikasi konsol yang digunakan untuk menghasilkan output:

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})";
        }
    }
}
krzychu
sumber
Tabel kasus ini sangat membantu. Terima kasih!
VoteCoffee
2

tidak ada perbedaan dalam bahasa inggris. hanya dalam budaya Turki perbedaan dapat ditemukan.

Stefanvds
sumber
13
Dan Anda yakin bahwa Turki adalah satu-satunya budaya di dunia yang memiliki aturan huruf besar berbeda dengan bahasa Inggris? Saya merasa sulit untuk percaya.
Joel Mueller
3
Turki adalah contoh yang paling sering digunakan, tetapi bukan satu-satunya. Dan itu bahasa, bukan budaya yang memiliki empat aku berbeda. Namun, +1 untuk bahasa Turki.
Armstrongest
pasti ada beberapa yang lain. kebanyakan ppl tidak akan pernah bertemu dengan bahasa-bahasa tersebut dalam pemrograman
Stefanvds
8
Tentu mereka akan melakukannya. Aplikasi Web terbuka untuk globe dan ada baiknya mengatur parameter Anda. Bagaimana jika Anda beroperasi pada database lama yang tidak melakukan unicode? Karakter apa yang akan Anda terima sebagai nama pengguna? Bagaimana jika Anda harus memasukkan nama Pelanggan ke dalam Legacy ERP yang dibangun di atas COBOL? Banyak kasus di mana budaya itu penting. Belum lagi, tanggal dan angka. 4.54 ditulis 4,54 dalam beberapa bahasa. Berpura-pura bahasa lain itu tidak ada tidak akan membuat Anda jauh dalam jangka panjang.
Armstrongest
jelas budaya penting untuk tanggal dan angka, saya hanya mengatakan sebagian besar ppl tidak akan pernah bertemu dengan bahasa yang memiliki hasil berbeda di toUpper dan toUpperInvariant.
Stefanvds