Trong C #, sự khác biệt giữa ToUpper () và ToUpperInvariant () là gì?


133

Trong C #, sự khác biệt giữa ToUpper()và là ToUpperInvariant()gì?

Bạn có thể đưa ra một ví dụ mà kết quả có thể khác nhau?


3
[Tổ chức] Câu hỏi này có nên gắn thẻ "quốc tế hóa" không?
jasso

Câu trả lời:


154

ToUppersử dụng văn hóa hiện tại. ToUpperInvariantsử dụng văn hóa bất biến.

Ví dụ kinh điển là Thổ Nhĩ Kỳ, trong đó chữ hoa của chữ "i" không phải là "tôi".

Mã mẫu cho thấy sự khác biệt:

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

Để biết thêm về tiếng Thổ Nhĩ Kỳ, xem bài đăng blog Thử nghiệm Thổ Nhĩ Kỳ này .

Tôi sẽ không ngạc nhiên khi biết rằng có nhiều vấn đề viết hoa khác xung quanh các nhân vật bị tách biệt, v.v ... Đây chỉ là một ví dụ tôi biết trên đỉnh đầu của mình ... một phần vì nó làm tôi bực mình nhiều năm trước ở Java, nơi tôi ở trên -tạo một chuỗi và so sánh nó với "MAIL". Điều đó đã không làm việc rất tốt ở Thổ Nhĩ Kỳ ...


45
haha Tôi đọc được suy nghĩ đó ... "'Thổ Nhĩ Kỳ' không có chữ 'i' trong đó"
Jeff Mercado

Đã gần đến năm 2019 và tôi đang có Visual Studio gợi ý ımagelàm tên trường Imagevà Unity 3D đang spam một lỗi nội bộ đối với bảng điều khiển Unable to find key name that matches 'rıght'trên Windows "tiếng Anh" với cài đặt khu vực Thổ Nhĩ Kỳ theo ngày và giờ. Có vẻ như đôi khi Microsoft thất bại trong bài kiểm tra Thổ Nhĩ Kỳ, ngôn ngữ của PC thậm chí không phải là tiếng Thổ Nhĩ Kỳ, chỉ là lol.
Guney Ozsan

28

Câu trả lời của Jon là hoàn hảo. Tôi chỉ muốn thêm đó ToUpperInvariantlà giống như gọi ToUpper(CultureInfo.InvariantCulture).

Điều đó làm cho ví dụ của Jon đơn giản hơn một chút:

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

Tôi cũng đã sử dụng New Times Roman vì đây là một phông chữ hay hơn.

Tôi cũng đặt Formcủa Fonttài sản thay vì hai Labelđiều khiển bởi vì Fonttài sản được thừa hưởng.

Và tôi đã giảm một vài dòng khác chỉ vì tôi thích mã nhỏ gọn (ví dụ, không sản xuất).

Tôi thực sự không có gì tốt hơn để làm vào lúc này.


5
"Câu trả lời của Jon là hoàn hảo." Nói về một tuyên bố dư thừa. ;)
krillgar

1
Phương pháp ToUpper không có quá tải tham số cho tôi? phiên bản cũ hơn có? Tôi không hiểu điều đó
batmaci

Tôi không biết, nó được ghi lại ở đây: msdn.microsoft.com/en-us/l
Library / system.opes.toupper.aspx


12

String.ToUpperString.ToLowercó thể đưa ra kết quả khác nhau cho các nền văn hóa khác nhau. Ví dụ được biết đến nhiều nhất là ví dụ tiếng Thổ Nhĩ Kỳ , trong đó chuyển đổi chữ "i" chữ thường thành chữ hoa, không dẫn đến chữ "I" được viết hoa, nhưng trong chữ "I" trong tiếng Thổ Nhĩ Kỳ.

Viết hoa chữ I tùy thuộc vào văn hóa, hàng trên - chữ thường, hàng dưới - chữ in hoa

Đối với tôi thật khó hiểu ngay cả với hình trên ( nguồn ), tôi đã viết một chương trình (xem mã nguồn bên dưới) để xem đầu ra chính xác cho ví dụ tiếng Thổ Nhĩ Kỳ:

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

Bạn có thể thấy:

  1. Chữ hoa viết thường và chữ in thường viết hoa cho kết quả khác nhau cho văn hóa bất biến và văn hóa Thổ Nhĩ Kỳ.
  2. Chữ hoa viết thường và chữ thường viết thường không có tác dụng, bất kể văn hóa là gì.
  3. Culture.CultureInvariant để lại các ký tự Thổ Nhĩ Kỳ
  4. ToUpperToLowercó thể đảo ngược, đó là hạ thấp một nhân vật sau khi vượt qua nó, đưa nó về dạng ban đầu, miễn là đối với cả hai hoạt động, cùng một nền văn hóa đã được sử dụng.

Theo MSDN , đối với Char.ToUpper và Char.ToLower Thổ Nhĩ Kỳ và Azeri là những nền văn hóa duy nhất bị ảnh hưởng bởi vì họ là những người duy nhất có sự khác biệt về vỏ bọc một ký tự. Đối với chuỗi, có thể có nhiều nền văn hóa bị ảnh hưởng.


Mã nguồn của ứng dụng giao diện điều khiển được sử dụng để tạo đầu ra:

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

Bảng các trường hợp rất hữu ích. Cảm ơn!
VoteCoffee


2

không có sự khác biệt trong tiếng Anh. chỉ trong văn hóa Thổ Nhĩ Kỳ một sự khác biệt có thể được tìm thấy.


13
Và bạn có chắc rằng Thổ Nhĩ Kỳ là nền văn hóa duy nhất trên thế giới có các quy tắc viết hoa khác với tiếng Anh không? Tôi thấy khó tin.
Joel Mueller

3
Thổ Nhĩ Kỳ là ví dụ thường được sử dụng nhất, nhưng không phải là ví dụ duy nhất. Và đó là ngôn ngữ, không phải văn hóa có bốn cái tôi khác nhau. Tuy nhiên, +1 cho Thổ Nhĩ Kỳ.
Armstrongest

chắc chắn phải có một số người khác. hầu hết các ppl sẽ không bao giờ gặp những ngôn ngữ đó trong lập trình
Stefanvds

8
Chắc chắn họ sẽ. Các ứng dụng web được mở trên toàn cầu và thật tốt khi đặt tham số của bạn. Điều gì xảy ra nếu bạn đang hoạt động trên cơ sở dữ liệu cũ mà không làm unicode? Những ký tự nào bạn sẽ chấp nhận làm tên người dùng? Điều gì sẽ xảy ra nếu bạn phải đặt tên Khách hàng vào ERP kế thừa được xây dựng trên COBOL? Rất nhiều trường hợp văn hóa là quan trọng. Chưa kể, ngày và số. 4,54 được viết 4,54 trong một số ngôn ngữ. Giả vờ những ngôn ngữ khác không tồn tại sẽ không giúp bạn tiến xa trong thời gian dài.
Armstrongest

rõ ràng các nền văn hóa rất quan trọng đối với ngày và số, tôi chỉ nói rằng hầu hết các ppl sẽ không bao giờ gặp các ngôn ngữ có kết quả khác nhau trong toUpper và toUpperInvariant.
Stefanvd
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.