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

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

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

108
demandé sur Nelson Reis 2010-08-23 21:49:29

7 réponses

ToUpper utilise la culture courante. ToUpperInvariant utilise la culture invariante.

L'exemple canonique est la Turquie, où le cas supérieur de" i "n'est 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 plus de détails sur le turc, voir ce Turkey Test blog post .

Je ne serais pas surpris d'entendre qu'il y a d'autres problèmes de capitalisation autour élidés personnages ... Ce n'est qu'un exemple que je connais du haut de ma tête... en partie parce qu'il m'a mordu il y a des années à Java, où j'étais en train de comparer une chaîne avec "MAIL". Ça n'a pas très bien marché en Turquie...

131
répondu Jon Skeet 2010-08-23 17:56:59

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

ce qui 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 aussi utilisé New Times Roman parce que c'est une police plus cool.

j'ai aussi placé la propriété Form 's Font au lieu des deux Label contrôles parce que la propriété Font est héritée.

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

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

24
répondu Tergiver 2010-08-23 19:13:09

Démarrer avec MSDN

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

la méthode ToUpperInvariant est équivalent à ToUpper (CultureInfo.Culture invariante)

ce n'est pas parce qu'une capitale i est 'I' en anglais qu'il en est ainsi.

14
répondu CaffGeek 2010-08-23 17:51:59

String.ToUpper et String.ToLower peut donner des résultats différents en fonction des différentes cultures. L'exemple le plus connu est l'exemple Turc , pour lequel la conversion en majuscules du latin "i" n'entraîne pas un Majuscule du latin "I", mais dans le Turc "I".

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

quant à moi, il était confus même avec l'image ci-dessus ( source ), J'ai écrit un programme (voir 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 lettres majuscules minuscules et les lettres minuscules majuscules donnent des résultats différents pour la culture invariante et la culture turque.
  2. majuscules et minuscules 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-à mettre en minuscule, un caractère après uppercasing, il apporte à la forme originale, aussi longtemps que pour les deux opérations à la même culture, a été utilisé.

Selon MSDN , pour Char.ToUpper et Char.ToLower les Turcs et les Azéris sont les seules cultures affectées parce qu'ils sont les seuls avec un seul corps de caractère différence. Pour les cordes, il pourrait y avoir plus de cultures affectées.


code Source d'une application de 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})";
        }
    }
}
6
répondu krzychu 2016-04-28 13:44:15

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

Microsoft documentation explique les différences et donne des exemples de résultats différents.

3
répondu KrisTrip 2010-08-23 17:51:41

ToUpperInvariant utilise les règles de la culture invariante

3
répondu taylonr 2010-08-23 17:52:14

il n'y a pas de différence en anglais. seulement dans la culture turque une différence peut être trouvé.

2
répondu Stefanvds 2010-08-23 17:53:22