In C # qual è la differenza tra ToUpper () e ToUpperInvariant ()?


133

In C #, qual è la differenza tra ToUpper()e ToUpperInvariant()?

Puoi fare un esempio in cui i risultati potrebbero essere diversi?


3
[Organizzazione] Questa domanda dovrebbe avere il tag "internazionalizzazione"?
Jasso,

Risposte:


154

ToUpperusa la cultura attuale. ToUpperInvariantusa la cultura invariante.

L'esempio canonico è la Turchia, dove il maiuscolo di "i" non è "I".

Codice di esempio che mostra la differenza:

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

Per ulteriori informazioni sul turco, consulta questo post sul blog Test Turchia .

Non sarei sorpreso di sapere che ci sono vari altri problemi di capitalizzazione attorno ai personaggi elisi, ecc. Questo è solo un esempio che conosco dalla cima della mia testa ... in parte perché mi ha morso anni fa a Java, dove ero superiore -casando una stringa e confrontandola con "MAIL". Non ha funzionato così bene in Turchia ...


45
ahah ho letto quel pensiero ... "" La Turchia "non contiene una lettera" io ""
Jeff Mercado,

È quasi il 2019 e ho Visual Studio che suggerisce ımagecome nome di campo Imagee Unity 3D spamming un errore interno alla console Unable to find key name that matches 'rıght'su un Windows "inglese" con le impostazioni regionali della Turchia per data e ora. Sembra che a volte anche Microsoft non superi il test di Turchia, la lingua di un PC non è nemmeno turco, ma solo lol.
Guney Ozsan,

28

La risposta di Jon è perfetta. Volevo solo aggiungere che ToUpperInvariantequivale a chiamare ToUpper(CultureInfo.InvariantCulture).

Questo rende l'esempio di Jon un po 'più semplice:

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

Ho anche usato New Times Roman perché è un carattere più interessante.

Ho anche impostare la Form's Fontproprietà invece dei due Labelcontrolli perché la Fontproprietà è ereditata.

E ho ridotto alcune altre righe solo perché mi piace il codice compatto (esempio, non di produzione).

Non avevo davvero niente di meglio da fare al momento.


5
"La risposta di Jon è perfetta." Parla di una dichiarazione ridondante. ;)
Krillgar,

1
Il metodo ToUpper non ha alcun sovraccarico di parametri per me? aveva la versione precedente? Non capisco
batmaci,



12

String.ToUppere String.ToLowerpuò dare risultati diversi date culture diverse. L'esempio più noto è l'esempio turco , per il quale la conversione della "i" latina minuscola in maiuscola non comporta un "I" latino maiuscolo, ma nella "I" turca.

Lettere maiuscole in base alla cultura, riga superiore - lettere minuscole, riga inferiore - lettere maiuscole

Quanto a me era confuso anche con l'immagine sopra ( sorgente ), ho scritto un programma (vedi il codice sorgente di seguito) per vedere l'output esatto per l'esempio turco:

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

Come potete vedere:

  1. Lettere maiuscole e minuscole in maiuscolo danno risultati diversi per la cultura invariante e la cultura turca.
  2. Il maiuscolo e il minuscolo non hanno alcun effetto, indipendentemente dalla cultura.
  3. Culture.CultureInvariant lascia i caratteri turchi così come sono
  4. ToUppere ToLowersono reversibili, ovvero minare un personaggio dopo averlo maiuscolo, lo riporta alla forma originale, purché per entrambe le operazioni sia stata usata la stessa cultura.

Secondo MSDN , per Char.ToUpper e Char.ToLower i turchi e gli azeri sono le uniche culture interessate perché sono le uniche con differenze di involucro a carattere singolo. Per le stringhe, potrebbero esserci più culture interessate.


Codice sorgente di un'applicazione console utilizzata per generare l'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})";
        }
    }
}

La tabella dei casi è stata molto utile. Grazie!
VoteCoffee


2

non c'è differenza in inglese. solo nella cultura turca si può trovare una differenza.


13
E sei sicuro che il turco sia l'unica cultura al mondo che ha regole diverse per l'inglese in maiuscolo? Lo trovo difficile da credere.
Joel Mueller,

3
Il turco è l'esempio più usato, ma non l'unico. Ed è la lingua, non la cultura che ha quattro diversi io. Ancora, +1 per il turco.
Armstrongest,

certo che ce ne devono essere altri. la maggior parte dei ppl non incontrerà mai quei linguaggi in programmazione comunque
Stefanvds il

8
Sicuro che lo faranno. Le applicazioni Web sono aperte al mondo ed è bene impostare i parametri. Che cosa succede se si opera su un database legacy che non fa unicode? Quali personaggi accetterai come nome utente? Cosa succede se devi inserire i nomi dei clienti in un ERP legacy basato su COBOL? Molti casi in cui la cultura è importante. Per non parlare di date e numeri. 4.54 è scritto 4.54 in alcune lingue. Fingere che quelle altre lingue non esistano non ti porterà molto lontano nel lungo periodo.
Armstrongest,

ovviamente le culture sono importanti per date e numeri, sto solo dicendo che la maggior parte dei ppl non incontrerà mai le lingue che hanno un risultato diverso in Topper e Topper Invariant.
Stefanvds,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.