En C #, quelle est la différence entre ToUpper()
et ToUpperInvariant()
?
Pouvez-vous donner un exemple où les résultats pourraient être différents?
En C #, quelle est la différence entre ToUpper()
et ToUpperInvariant()
?
Pouvez-vous donner un exemple où les résultats pourraient être différents?
Réponses:
ToUpper
utilise la culture actuelle. ToUpperInvariant
utilise la culture invariante.
L'exemple canonique est la Turquie, où la majuscule de «i» n'est pas «je».
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 cet 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 élidés, etc. Ce n'est qu'un exemple que je connais d'emblée ... en partie parce que cela m'a mordu il y a des années à Java, où j'étais supérieur -caser une chaîne et la comparer avec "MAIL". Cela n'a pas si bien fonctionné en Turquie ...
ımage
demande à Visual Studio de suggérer comme nom de champ Image
et de spam Unity 3D une erreur interne à la console Unable to find key name that matches 'rıght'
sur un Windows "anglais" avec les paramètres régionaux de Turquie pour la date et l'heure. On dirait que parfois même Microsoft échoue au test de la Turquie, la langue d'un PC n'est même pas le turc, juste lol.
La réponse de Jon est parfaite. Je voulais juste ajouter que ToUpperInvariant
c'est la même chose 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 aussi utilisé New Times Roman car c'est une police plus cool.
J'ai également mis le Form
'sFont
propriété au lieu des deux Label
contrôles car la Font
propriété est héritée.
Et j'ai réduit quelques autres lignes simplement parce que j'aime le code compact (exemple, pas de 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)
Ce n'est pas toujours parce qu'un i majuscule est «je» en anglais.
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 minuscule "i" en majuscule ne se traduit pas par un "I" latin majuscule, mais par 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 en minuscules un caractère après l'avoir mis en majuscules, 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 avec des différences de casse à un seul caractère. Pour les chaînes, d'autres cultures peuvent être 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.