ใน C # ความแตกต่างระหว่าง ToUpper () และ ToUpperInvariant () คืออะไร?


135

ใน C # ความแตกต่างระหว่างToUpper()และToUpperInvariant()อย่างไร?

คุณช่วยยกตัวอย่างที่ผลลัพธ์อาจแตกต่างกันได้ไหม


3
[องค์กร] คำถามนี้ควรมีแท็ก "ความเป็นสากล" หรือไม่?
jasso

คำตอบ:


156

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

สำหรับข้อมูลเพิ่มเติมเกี่ยวตุรกี, เห็นนี้โพสต์บล็อกตุรกีทดสอบ

ฉันจะไม่แปลกใจที่ได้ยินว่ามีปัญหาการใช้อักษรตัวพิมพ์ใหญ่อื่น ๆ อีกมากมายเกี่ยวกับอักขระที่มีการเล็ดลอด ฯลฯ นี่เป็นเพียงตัวอย่างหนึ่งที่ฉันรู้จากด้านบนของหัว ... - ใส่สายอักขระและเปรียบเทียบกับ "MAIL" นั่นไม่ได้ผลดีนักในตุรกี ...


47
ฮ่าฮ่าฉันอ่านแล้วคิดว่า ... "" ตุรกี "ไม่มีตัวอักษร" i "อยู่ในนั้น"
Jeff Mercado

1
เกือบปี 2019 และฉันมี Visual Studio ที่แนะนำımageเป็นชื่อฟิลด์Imageและ Unity 3D ส่งสแปมข้อผิดพลาดภายในไปยังคอนโซลUnable to find key name that matches 'rıght'บน Windows "ภาษาอังกฤษ" พร้อมการตั้งค่าภูมิภาคตุรกีสำหรับวันที่และเวลา ดูเหมือนว่าบางครั้ง Microsoft จะล้มเหลวในการทดสอบภาษาตุรกีภาษาของพีซีไม่ใช่ภาษาตุรกีเลย
Guney Ozsan

28

คำตอบของจอนสมบูรณ์แบบ ฉันแค่อยากจะเพิ่มว่าเป็นเช่นเดียวกับการเรียกToUpperInvariantToUpper(CultureInfo.InvariantCulture)

นั่นทำให้ตัวอย่างของจอนง่ายขึ้นเล็กน้อย:

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คุณสมบัติที่เป็นกรรมพันธุ์

และฉันลดบรรทัดอื่น ๆ ลงเล็กน้อยเพียงเพราะฉันชอบโค้ดขนาดกะทัดรัด (ตัวอย่างไม่ใช่การผลิต)

ฉันไม่มีอะไรดีไปกว่าที่จะทำในขณะนี้


5
"คำตอบของจอนสมบูรณ์แบบ" พูดถึงคำสั่งซ้ำซ้อน ;)
krillgar

1
วิธีการ ToUpper ไม่มีพารามิเตอร์เกินสำหรับฉันหรือไม่? รุ่นเก่ามีไหม ฉันไม่เข้าใจ
Emil

ฉันไม่ทราบว่ามีการบันทึกไว้ที่นี่: msdn.microsoft.com/en-us/library/system.string.toupper.aspx
Tergiver


13

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)

อย่างที่เห็น:

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

ตารางคดีมีประโยชน์มาก ขอบคุณ!
VoteCoffee


2

ไม่มีความแตกต่างในภาษาอังกฤษ เฉพาะในวัฒนธรรมตุรกีเท่านั้นที่สามารถพบความแตกต่างได้


14
และคุณแน่ใจหรือไม่ว่าภาษาตุรกีเป็นวัฒนธรรมเดียวในโลกที่มีกฎสำหรับตัวพิมพ์ใหญ่ที่แตกต่างจากภาษาอังกฤษ ฉันพบว่ามันยากที่จะเชื่อ
Joel Mueller

3
ภาษาตุรกีเป็นตัวอย่างที่ใช้บ่อยที่สุด แต่ไม่ใช่เพียงตัวอย่างเดียว และเป็นภาษาไม่ใช่วัฒนธรรมที่มีสี่อย่างที่แตกต่างกัน ยังคง +1 สำหรับตุรกี
Armstrongest

แน่ใจว่าต้องมีคนอื่น ๆ คนส่วนใหญ่จะไม่เคยพบกับภาษาเหล่านั้นในการเขียนโปรแกรมเลย
Stefanvds

9
แน่นอนว่าพวกเขาจะ เว็บแอปพลิเคชันเปิดให้บริการทั่วโลกและเป็นการดีที่จะตั้งค่าพารามิเตอร์ของคุณ จะเกิดอะไรขึ้นถ้าคุณใช้งานฐานข้อมูลเดิมที่ไม่ได้ทำ Unicode? คุณจะยอมรับตัวอักษรใดเป็นชื่อผู้ใช้? จะเกิดอะไรขึ้นถ้าคุณต้องใส่ชื่อลูกค้าลงใน Legacy ERP ที่สร้างขึ้นบน COBOL? หลายกรณีที่วัฒนธรรมมีความสำคัญ ไม่ต้องพูดถึงวันที่และตัวเลข 4.54 มีการเขียน 4,54 ในบางภาษา การแสร้งทำเป็นภาษาอื่น ๆ เหล่านั้นจะไม่ทำให้คุณไปได้ไกลในระยะยาว
Armstrongest

เห็นได้ชัดว่าวัฒนธรรมมีความสำคัญสำหรับวันที่และตัวเลขฉันแค่บอกว่าคนส่วนใหญ่จะไม่ตรงตามภาษาที่มีผลลัพธ์ที่แตกต่างกันใน toUpper และ toUpperInvariant
Stefanvds
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.