C#でToUpper()とToUpperInvariant()の違いは何ですか?


133

C#では、違いは何であるToUpper()とはToUpperInvariant()

結果が異なる例を挙げていただけますか?


3
[組織]この質問には「国際化」というタグを付ける必要がありますか?
jasso 2010

回答:


154

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

トルコ語について詳しくは、こちらのトルコテストのブログ投稿をご覧ください。

省略された文字など、他にもさまざまな大文字の問題があることを聞いて驚かないでしょう。これは、頭上で知っているほんの一例です...何年か前にJavaで私がアッパーだったためです-文字列を囲み、それを "MAIL"と比較します。トルコではうまくいきませんでした...


45
ハハ私はその考えを読んだ...「 'トルコ'には 'i'の文字が含まれていない」
ジェフ・メルカド

それはほぼ2019年で、私はVisual Studioにımageフィールド名としてImage、Unity 3D Unable to find key name that matches 'rıght'がトルコ語の日付と時刻の地域設定を持つ「英語」のWindowsのコンソールに内部エラーをスパム送信することを提案しています。時々マイクロソフトさえトルコのテストに失敗するように見えます、PCの言語はトルコ語でさえない、ただの笑いです。
Guney Ozsan、

28

ジョンの答えは完璧です。追加したかったのToUpperInvariantは、を呼び出すのと同じToUpper(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もクールなフォントなので使用しました。

プロパティは継承されるため、2つのコントロールの代わりにFormFontプロパティも設定します。LabelFont

また、コンパクトな(例ではなく、プロダクション)コードが好きなだけで、他の数行を削減しました。

現時点で本当にやるべきことは何もありませんでした。


5
「ジョンの答えは完璧です。」冗長なステートメントについて話します。;)
2016年

1
ToUpperメソッドには、パラメーターのオーバーロードはありませんか?古いバージョンはありましたか?
わかり

わかりません。ここに記載されています:msdn.microsoft.com/en-us/library/system.string.toupper.aspx
Tergiver


12

String.ToUpperそしてString.ToLower異文化与えられた異なる結果を与えることができます。最もよく知られている例はトルコ語の例で、小文字のラテン語「i」を大文字に変換しても、大文字のラテン語「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. 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

英語に違いはありません。トルコ文化でのみ違いが見られます。


13
そして、あなたはトルコ語が大文字と英語の異なる規則を持つ世界で唯一の文化であることを確信していますか?それを信じるのは難しいと思います。
Joel Mueller

3
トルコ語が最もよく使用される例ですが、唯一の例ではありません。そして私が4つの異なる文化を持っているのは言語ではありません。それでも、トルコ語は+1。
Armstrongest

他にもいくつかあるに違いない。とにかく、ほとんどのPPLがプログラミングでこれらの言語に出会うことは決してありません
Stefanvds

8
もちろんです。Webアプリケーションは世界中に公開されており、パラメーターを設定することをお勧めします。ユニコードを実行しないレガシーデータベースで操作している場合はどうなりますか?ユーザー名としてどのような文字を受け入れますか?COBOLで構築されたレガシーERPに顧客名を入力する必要がある場合はどうなりますか?文化が重要である多くの場合。言うまでもなく、日付と数値。4.54はいくつかの言語で4,54と書かれています。他の言語が存在しないふりをしても、長い目で見ればそれほど遠くはありません。
Armstrongest

明らかに、文化は日付と数値にとって重要です。私はほとんどのpplがtoUpperとtoUpperInvariantで異なる結果を持つ言語に会うことは決してないと言っています。
Stefanvds、2010
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.