Como você parece estar ciente, colocar duas strings em minúsculas e compará-las não é o mesmo que fazer uma comparação de maiúsculas e minúsculas. Existem muitas razões para isso. Por exemplo, o padrão Unicode permite que o texto com diacríticos seja codificado de várias maneiras. Alguns caracteres incluem o caractere base e o diacrítico em um único ponto de código. Esses caracteres também podem ser representados como o caractere base seguido por um caractere diacrítico de combinação. Essas duas representações são iguais para todos os fins, e as comparações de strings de reconhecimento de cultura no .NET Framework irão identificá-los corretamente como iguais, com CurrentCulture ou InvariantCulture (com ou sem IgnoreCase). Uma comparação ordinal, por outro lado, os considerará incorretamente como desiguais.
Infelizmente, switch
não faz nada além de uma comparação ordinal. Uma comparação ordinal é adequada para certos tipos de aplicativos, como analisar um arquivo ASCII com códigos rigidamente definidos, mas a comparação de strings ordinais é incorreta para a maioria dos outros usos.
O que fiz no passado para obter o comportamento correto é apenas simular minha própria instrução switch. Existem muitas maneiras de fazer isso. Uma maneira seria criar um List<T>
par de strings case e delegados. A lista pode ser pesquisada usando a comparação de string adequada. Quando a correspondência é encontrada, o delegado associado pode ser chamado.
Outra opção é fazer a cadeia óbvia de if
afirmações. Geralmente, isso não é tão ruim quanto parece, já que a estrutura é muito regular.
A melhor coisa sobre isso é que não há realmente nenhuma penalidade de desempenho em simular a funcionalidade de seu próprio switch ao comparar com strings. O sistema não vai fazer uma tabela de pulos O (1) da maneira que faz com inteiros, então vai comparar cada string uma por vez de qualquer maneira.
Se houver muitos casos a serem comparados e o desempenho for um problema, a List<T>
opção descrita acima pode ser substituída por um dicionário classificado ou tabela de hash. Então, o desempenho pode corresponder ou exceder a opção de instrução switch.
Aqui está um exemplo da lista de delegados:
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();
}
Claro, você provavelmente desejará adicionar alguns parâmetros padrão e, possivelmente, um tipo de retorno ao delegado CustomSwitchDestination. E você vai querer fazer nomes melhores!
Se o comportamento de cada um dos seus casos não puder ser delegado à invocação dessa maneira, como se parâmetros diferentes forem necessários, você estará preso a if
instruções encadeadas . Eu também fiz isso algumas vezes.
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()
? Além disso, ele não está comparando duas strings desconhecidas , ele está comparando uma string desconhecida a uma string conhecida. Portanto, contanto que ele saiba como codificar a representação adequada em maiúsculas ou minúsculas, o bloco de comutação deve funcionar bem.