Comme vous semblez le savoir, mettre deux chaînes en minuscules et les comparer n'est pas la même chose que de faire une comparaison sans casse. Il y a de nombreuses raisons à cela. Par exemple, la norme Unicode permet de coder du texte avec des signes diacritiques de plusieurs manières. Certains caractères incluent à la fois le caractère de base et le signe diacritique dans un seul point de code. Ces caractères peuvent également être représentés comme le caractère de base suivi d'un caractère diacritique de combinaison. Ces deux représentations sont égales à toutes fins, et les comparaisons de chaînes tenant compte de la culture dans le .NET Framework les identifieront correctement comme étant égales, avec CurrentCulture ou InvariantCulture (avec ou sans IgnoreCase). Une comparaison ordinale, en revanche, les considérera à tort comme inégales.
Malheureusement, switch
ne fait rien d'autre qu'une comparaison ordinale. Une comparaison ordinale convient à certains types d'applications, comme l'analyse d'un fichier ASCII avec des codes définis de manière rigide, mais la comparaison de chaînes ordinales est incorrecte pour la plupart des autres utilisations.
Ce que j'ai fait dans le passé pour obtenir le bon comportement, c'est juste une maquette de ma propre instruction switch. Il y a plusieurs manières de faire ça. Une façon serait de créer une List<T>
paire de chaînes de cas et de délégués. La liste peut être recherchée en utilisant la comparaison de chaînes appropriée. Lorsque la correspondance est trouvée, le délégué associé peut être appelé.
Une autre option est de faire la chaîne évidente d' if
instructions. Cela s'avère généralement moins grave qu'il n'y paraît, car la structure est très régulière.
La grande chose à ce sujet est qu'il n'y a pas vraiment de pénalité en termes de performances à simuler votre propre fonctionnalité de commutateur lors de la comparaison avec des chaînes. Le système ne va pas créer une table de saut O (1) comme il le peut avec des entiers, il va donc comparer chaque chaîne une à la fois de toute façon.
S'il y a de nombreux cas à comparer et que les performances sont un problème, l' List<T>
option décrite ci-dessus peut être remplacée par un dictionnaire trié ou une table de hachage. Ensuite, les performances peuvent potentiellement correspondre ou dépasser l'option d'instruction switch.
Voici un exemple de la liste des délégués:
delegate void CustomSwitchDestination();
List<KeyValuePair<string, CustomSwitchDestination>> customSwitchList;
CustomSwitchDestination defaultSwitchDestination = new CustomSwitchDestination(NoMatchFound);
void CustomSwitch(string value)
{
foreach (var switchOption in customSwitchList)
if (switchOption.Key.Equals(value, StringComparison.InvariantCultureIgnoreCase))
{
switchOption.Value.Invoke();
return;
}
defaultSwitchDestination.Invoke();
}
Bien sûr, vous souhaiterez probablement ajouter des paramètres standard et éventuellement un type de retour au délégué CustomSwitchDestination. Et vous voudrez vous faire de meilleurs noms!
Si le comportement de chacun de vos cas ne permet pas de déléguer l'invocation de cette manière, par exemple si des paramètres différents sont nécessaires, alors vous êtes coincé avec des if
instructions chaînées . J'ai également fait cela plusieurs fois.
if (s.Equals("house", StringComparison.InvariantCultureIgnoreCase))
{
s = "window";
}
else if (s.Equals("business", StringComparison.InvariantCultureIgnoreCase))
{
s = "really big window";
}
else if (s.Equals("school", StringComparison.InvariantCultureIgnoreCase))
{
s = "broken window";
}
ToUpperInvariant()
ouToLowerInvariant()
? De plus, il ne compare pas deux chaînes inconnues , il compare une chaîne inconnue à une chaîne connue. Ainsi, tant qu'il sait comment coder en dur la représentation en majuscules ou minuscules appropriée, le bloc de commutation devrait fonctionner correctement.