web-dev-qa-db-fra.com

En C # quelle est la différence entre ToUpper () et ToUpperInvariant ()?

En C #, quelle est la différence entre ToUpper() et ToUpperInvariant()?

Pouvez-vous donner un exemple où les résultats pourraient être différents?

118
Lill Lansey

ToUpper utilise la culture actuelle. ToUpperInvariant utilise la culture invariante.

L'exemple canonique est la Turquie, où les majuscules de "i" ne sont pas "I".

Exemple de code montrant la différence:

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

Pour en savoir plus sur le turc, consultez ce Article de blog Turkey Test .

Je ne serais pas surpris d'entendre qu'il y a divers autres problèmes de capitalisation autour des personnages élus etc. -caser une chaîne et la comparer avec "MAIL". Cela n'a pas si bien fonctionné en Turquie ...

140
Jon Skeet

La réponse de Jon est parfaite. Je voulais juste ajouter que ToUpperInvariant est le même que d'appeler ToUpper(CultureInfo.InvariantCulture).

Cela rend l'exemple de Jon un peu plus simple:

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

J'ai également utilisé New Times Roman parce que c'est une police plus cool.

J'ai également défini la propriété Form de Font au lieu des deux contrôles Label car la propriété Font est héritée.

Et j'ai réduit quelques autres lignes juste parce que j'aime le code compact (par exemple, pas la production).

Je n'avais vraiment rien de mieux à faire pour le moment.

25
Tergiver

Commencez avec MSDN

http://msdn.Microsoft.com/en-us/library/system.string.toupperinvariant.aspx

La méthode ToUpperInvariant est équivalente à ToUpper (CultureInfo.InvariantCulture)

Tout simplement parce qu'une majuscule i est 'I' en anglais, doesn ' t toujours le faire.

15
CaffGeek

String.ToUpper et String.ToLower peut donner des résultats différents selon les cultures. L'exemple le plus connu est l'exemple turc , pour lequel la conversion du latin "i" minuscule en majuscule, n'entraîne pas un "I" latin majuscule, mais le "I" turc.

Capitalization of I depending on culture, upper row - lower case letters, lower row - upper case letters

Quant à moi, c'était déroutant même avec l'image ci-dessus ( source ), j'ai écrit un programme (voir le code source ci-dessous) pour voir la sortie exacte de l'exemple turc:

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

Comme vous pouvez le voir:

  1. Les majuscules et les minuscules majuscules donnent des résultats différents pour la culture invariante et la culture turque.
  2. Les majuscules et les minuscules majuscules n'ont aucun effet, quelle que soit la culture.
  3. Culture.CultureInvariant laisse les caractères turcs tels quels
  4. ToUpper et ToLower sont réversibles, c'est-à-dire que la mise en minuscule d'un caractère après sa mise en majuscule le ramène à la forme d'origine, tant que pour les deux opérations la même culture a été utilisée.

Selon MSDN , pour Char.ToUpper et Char.ToLower, le turc et l'azéri sont les seules cultures affectées car ce sont les seules qui présentent des différences de casse à un seul caractère. Pour les chaînes, il peut y avoir plus de cultures affectées.


Code source d'une application console utilisée pour générer la sortie:

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

ToUpperInvariant utilise les règles de la culture invariante

3
taylonr

il n'y a pas de différence en anglais. ce n'est que dans la culture turque qu'une différence peut être trouvée.

2
Stefanvds