En C #, quelle est la différence entre ToUpper()
et ToUpperInvariant()
?
Pouvez-vous donner un exemple où les résultats pourraient être différents?
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 ...
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.
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.
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.
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:
Culture.CultureInvariant
laisse les caractères turcs tels quelsToUpper
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})";
}
}
}
ToUpperInvariant utilise les règles de la culture invariante
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.