Basta ya de investigar por internet porque has llegado al lugar perfecto, contamos con la respuesta que deseas pero sin complicaciones.
Solución:
Un enfoque más simple es simplemente poner en minúsculas su string antes de que entre en la declaración de cambio, y tenga los casos más bajos.
En realidad, la parte superior es un poco mejor desde el punto de vista de un rendimiento de nanosegundos extremo puro, pero menos natural a la vista.
P.ej:
string s = "house";
switch (s.ToLower())
case "house":
s = "window";
break;
Como parece saber, poner dos cadenas en minúsculas y compararlas no es lo mismo que hacer una comparación de ignorar mayúsculas y minúsculas. Hay muchas razones para esto. Por ejemplo, el estándar Unicode permite que el texto con signos diacríticos se codifique de varias formas. Algunos caracteres incluyen tanto el carácter base como el diacrítico en un solo punto de código. Estos caracteres también se pueden representar como el carácter base seguido de un carácter diacrítico combinado. Estas dos representaciones son iguales a todos los efectos, y la conciencia cultural string las comparaciones en .NET Framework los identificarán correctamente como iguales, ya sea con CurrentCulture o InvariantCulture (con o sin IgnoreCase). Una comparación ordinal, por otro lado, los considerará incorrectamente como desiguales.
Desafortunadamente, switch
no hace nada más que una comparación ordinal. Una comparación ordinal está bien para ciertos tipos de aplicaciones, como analizar un archivo ASCII con códigos rígidamente definidos, pero ordinal string la comparación es incorrecta para la mayoría de los otros usos.
Lo que he hecho en el pasado para obtener el comportamiento correcto es simplemente simular mi propia declaración de cambio. Hay muchas formas de hacer esto. Una forma sería crear un List
de pares de cadenas de casos y delegados. La lista se puede buscar utilizando el string comparación. Cuando se encuentra la coincidencia, se puede invocar al delegado asociado.
Otra opción es hacer la cadena obvia de if
declaraciones. Por lo general, esto no resulta tan malo como parece, ya que la estructura es muy regular.
Lo mejor de esto es que realmente no hay ninguna penalización de rendimiento al simular su propia funcionalidad de interruptor cuando se compara con cadenas. El sistema no va a hacer una tabla de saltos O(1) de la forma en que lo hace con números enteros, por lo que va a comparar cada string uno a la vez de todos modos.
Si hay muchos casos para comparar, y el rendimiento es un problema, entonces el List
La opción descrita anteriormente podría reemplazarse con un diccionario ordenado o una tabla hash. Entonces, el rendimiento puede potencialmente igualar o superar la opción de declaración de cambio.
Aquí hay un ejemplo de la lista de delegados:
delegate void CustomSwitchDestination();
List> 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();
Por supuesto, probablemente desee agregar algunos parámetros estándar y posiblemente un tipo de retorno al delegado CustomSwitchDestination. ¡Y querrás hacer mejores nombres!
Si el comportamiento de cada uno de sus casos no es susceptible de delegar la invocación de esta manera, como si se necesitan diferentes parámetros, entonces está atascado con encadenado if
declaraciones También he hecho esto un par de veces.
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";
Perdón por esta nueva publicación a una pregunta anterior, pero hay una nueva opción para resolver este problema usando C# 7 (VS 2017).
C# 7 ahora ofrece “coincidencia de patrones” y se puede utilizar para abordar este problema de la siguiente manera:
string houseName = "house"; // value to be tested, ignoring case
string windowName; // switch block will set value here
switch (true)
case bool b when houseName.Equals("MyHouse", StringComparison.InvariantCultureIgnoreCase):
windowName = "MyWindow";
break;
case bool b when houseName.Equals("YourHouse", StringComparison.InvariantCultureIgnoreCase):
windowName = "YourWindow";
break;
case bool b when houseName.Equals("House", StringComparison.InvariantCultureIgnoreCase):
windowName = "Window";
break;
default:
windowName = null;
break;
Esta solución también trata el problema mencionado en la respuesta de @Jeffrey L Whitledge de que la comparación de cadenas que no distingue entre mayúsculas y minúsculas no es lo mismo que comparar dos cadenas en minúsculas.
Por cierto, hubo un artículo interesante en febrero de 2017 en la revista Visual Studio que describe la coincidencia de patrones y cómo se puede usar en bloques de casos. Eche un vistazo: Coincidencia de patrones en C# 7.0 Case Blocks
EDITAR
A la luz de la respuesta de @LewisM, es importante señalar que el switch
declaración tiene un comportamiento nuevo e interesante. Eso es que si tu case
declaración contiene una declaración de variable, entonces el valor especificado en el switch
parte se copia en la variable declarada en el case
. En el siguiente ejemplo, el valor true
se copia en la variable local b
. Además de eso, la variable b
no se usa, y existe sólo para que el when
cláusula a la case
declaración puede existir:
switch(true)
case bool b when houseName.Equals("X", StringComparison.InvariantCultureIgnoreCase):
windowName = "X-Window";):
break;
Como señala @LewisM, esto se puede usar para beneficiar, ese beneficio es que lo que se compara está realmente en el switch
afirmación, como ocurre con el uso clásico de la switch
declaración. Asimismo, los valores temporales declarados en el case
declaración puede evitar cambios no deseados o involuntarios en el valor original:
switch(houseName)
case string hn when hn.Equals("X", StringComparison.InvariantCultureIgnoreCase):
windowName = "X-Window";
break;
Sección de Reseñas y Valoraciones
Agradecemos que desees auxiliar nuestro ensayo añadiendo un comentario o puntuándolo te damos las gracias.