DEV Community

Cover image for Lógica de programación con estructuras de control en C#
Manuel Dávila
Manuel Dávila

Posted on • Updated on

Lógica de programación con estructuras de control en C#

¿Alguna vez te has preguntado cómo funcionan las aplicaciones que usas todos los días? Desde un simple juego en tu teléfono hasta una aplicación bancaria que gestiona tus finanzas, todos estos programas necesitan tomar decisiones y realizar acciones repetitivas. Y eso es exactamente lo que hacen las estructuras de control en C#.

Imagina que estás desarrollando una aplicación para un servicio de entrega de alimentos. Quieres que la aplicación muestre un mensaje diferente dependiendo de si el pedido está en camino, entregado o cancelado. Aquí es donde entra en juego el condicional "if".

Imagen de una caricatura con un letrero para decidir el camino de la izquierda o derecha

O tal vez estás construyendo una plataforma de streaming que personaliza recomendaciones de series y películas. Necesitas analizar el historial de visualizaciones de cada usuario para sugerir contenido nuevo. Aquí, los bucles "for" y "foreach" son esenciales para recorrer y procesar los datos.

Imagen de un loop infinito al ingresar a una puerta

Aquí aprenderemos cómo utilizar las estructuras de control en C# para hacer que nuestros programas tomen el camino que nosotros queremos.

Estructuras condicionales

1. Condicional If

El condicional "if" nos ayuda a decidir si una parte del código se ejecuta o no, dependiendo de si una condición es verdadera. Piénsalo como tomar decisiones en tiempo real en función de lo que está sucediendo.

Imagen de un diagrama de flujo con una estructura condicional if

Imagina que estás desarrollando una aplicación para un servicio de entrega de alimentos. Quieres que los usuarios reciban una notificación cuando su pedido esté listo para ser recogido. Podrías usar un condicional "if" para verificar si el pedido ha cambiado su estado a "listo para recoger". Si es así, envías una notificación al usuario para informarle.

if (pedido.Estado == EstadoPedido.ListoParaRecoger)
{
    EnviarNotificacion("Tu pedido está listo para recoger");
}
Enter fullscreen mode Exit fullscreen mode

En este ejemplo, el condicional "if" verifica si el usuario está inactivo (es decir, "usuarioActivo" es falso). Si lo está, se envía una notificación al usuario.

En este ejemplo, el condicional "if" verifica si el estado del pedido es "ListoParaRecoger". Si la condición es verdadera, se envía una notificación al usuario para informarle que puede ir a recoger su pedido.

2. Condicional If - Else

El condicional "if - else" nos ayuda a manejar situaciones donde hay más de una posible acción a tomar, dependiendo de si una condición es verdadera o falsa. Es como decir "si esto cumple, haz esto; de lo contrario, haz lo otro".

Imagen de un diagrama de flujo con una estructura condicional if - else

Supongamos que quieres mostrar un mensaje diferente a los usuarios dependiendo de si su pedido ha sido confirmado o no. Aquí es donde el condicional "if - else" resulta útil.

if (pedido.Estado == EstadoPedido.Confirmado)
{
    MostrarMensaje("Tu pedido ha sido confirmado y está siendo preparado.");
}
else
{
    MostrarMensaje("Lo sentimos, tu pedido no ha podido ser confirmado. Por favor, intenta nuevamente.");
}
Enter fullscreen mode Exit fullscreen mode

En este ejemplo, el condicional "if - else" verifica si el estado del pedido es Confirmado. Si el pedido está confirmado, se muestra un mensaje indicando que el pedido está siendo preparado. De lo contrario, se muestra un mensaje informando al usuario que el pedido no ha podido ser confirmado. Esto permite manejar diferentes estados del pedido de manera clara y estructurada.

3. Condicional If - Else If - Else

Las condicionales "if - else if - else" nos permiten evaluar una serie de condiciones en secuencia y ejecutar el bloque de código correspondiente a la primera condición que se cumpla. Es como decir "si esto cumple, haz esto; de lo contrario, si esto otro cumple, haz lo otro; y si ninguna de las anteriores sucede, haz esto otro".

Imagen de un diagrama de flujo con una estructura condicional if - else if - else

Si estas desarrollando un sistema de cálculo de tarifas de envío para una tienda en línea y dependiendo del peso del paquete y la distancia de envío, el sistema debe calcular diferentes tarifas de envío correspondiente, acá nos ayudaría esta condicional.

Imagina que necesitas calcular el tiempo estimado de entrega en función de la distancia y el tráfico, acá nos ayudaría esta condicional.

if (peso <= 2)
{
    tarifaEnvio = 5.99;
}
else if (peso <= 5)
{
    tarifaEnvio = 9.99;
}
else if (peso <= 10)
{
    tarifaEnvio = 14.99;
}
else
{
    tarifaEnvio = 19.99;
}

MostrarTarifaEnvio(tarifaEnvio);
Enter fullscreen mode Exit fullscreen mode

Es importante ordenar las condiciones de manera lógica y coherente para evitar errores y mejorar la legibilidad del código. El orden de tus condicionales es crucial, ya que una vez que se cumpla una condición, no se evaluarán las siguientes.

Existen los "if anidados", que se utilizan para evaluar múltiples condiciones de manera jerárquica y secuencial. Esto significa que dentro de un "if" se coloca otro bloque de "if", permitiendo tomar decisiones más complejas.

Por ejemplo, si necesitas determinar el tipo de oferta que se le debe mostrar a un cliente basado en su historial de pedidos y la disponibilidad actual de productos, puedes usar if anidados.

if (cliente.HistorialPedidos > 10)
{
    if (producto.Disponibilidad == "Alta")
    {
        MostrarOfertaEspecial("Descuento del 20% en tu próximo pedido");
    }
    else
    {
        MostrarOfertaEspecial("Descuento del 10% en tu próximo pedido");
    }
}
else
{
    MostrarOfertaEspecial("Obtén un 5% de descuento al referir a un amigo");
}
Enter fullscreen mode Exit fullscreen mode

Es una buena práctica refactorizar estos if anidados en un único "if - else if - else" cuando sea posible, para simplificar el código y mejorar su legibilidad.

4. Switch Case

El "switch case" es como una centralita de opciones que elige qué hacer basándose en el valor de una variable. Es especialmente útil cuando tienes varias opciones y cada una requiere una respuesta diferente. Es una alternativa más ordenada al uso de múltiples "if - else if - else".

Imagen de un diagrama de flujo con una estructura condicional switch

Si en tu aplicación quieres mostrar mensajes personalizados a los usuarios según el estado de su pedido, utilizar un "switch case" resulta ideal.

switch (pedido.Estado)
{
    case EstadoPedido.Pendiente:
        MostrarMensaje("Tu pedido está pendiente de confirmación.");
        break;
    case EstadoPedido.Confirmado:
        MostrarMensaje("¡Genial! Tu pedido ha sido confirmado y pronto estará en camino.");
        break;
    case EstadoPedido.EnCamino:
        MostrarMensaje("Tu pedido está en camino. ¡Prepárate para disfrutar!");
        break;
    case EstadoPedido.Entregado:
        MostrarMensaje("Tu pedido ha sido entregado. ¡Buen provecho!");
        break;
    case EstadoPedido.Cancelado:
        MostrarMensaje("Lo sentimos, tu pedido ha sido cancelado.");
        break;
    default:
        MostrarMensaje("Estado del pedido desconocido. Por favor, contacta con el soporte.");
        break;
}
Enter fullscreen mode Exit fullscreen mode

Cada "case" corresponde a un estado específico, y el programa ejecuta el bloque de código correspondiente solo si el valor del estado coincide. La instrucción break es importante porque evita que el código continúe ejecutando los siguientes bloques de "case" una vez que se encuentra una coincidencia.

El "switch case" hace que tu código sea más organizado, especialmente cuando hay varias condiciones posibles. Además, mejora la legibilidad y facilita la comprensión de lo que el programa está haciendo en cada situación.

5. Operador ternario

El operador ternario es útil para decisiones rápidas y sencillas, donde solo necesitas asignar diferente valor entre dos opciones. Es como decir "si esto es verdadero, asigna tal valor; si no, asigna esto otro", pero en una sola línea de código.

Imagen de un diagrama de flujo con una estructura condicional con operador ternario

Imagina que en tu aplicación quieres mostrar un mensaje que indique si el tiempo estimado de llegada es rápido o lento, dependiendo de si es menor o mayor a 30 minutos. El operador ternario es perfecto para este tipo de decisiones rápidas.

string mensajeTiempoEntrega = tiempoEntrega < 30 ? "Entrega rápida, buen provecho!" : "Tu pedido llegará pronto, gracias por tu paciencia.";

MostrarMensaje(mensajeTiempoEntrega);
Enter fullscreen mode Exit fullscreen mode

En este ejemplo, el operador ternario evalúa la condición tiempoEntrega < 30. Si es verdadera, asigna la cadena de texto "Entrega rápida, buen provecho!" a la variable mensajeTiempoEntrega. Si es falsa, asignará "Tu pedido llegará pronto, gracias por tu paciencia.".

Si no tuvieramos el operador ternario, utilizariamos el if-else de la siguiente forma para tener el mismo comportamiento:

string mensajeTiempoEntrega;
if (tiempoEntrega < 30)
{
    mensajeTiempoEntrega = "Entrega rápida, buen provecho!";
}
else
{
    mensajeTiempoEntrega = "Tu pedido llegará pronto, gracias por tu paciencia.";
}
MostrarMensaje(mensajeTiempoEntrega);
Enter fullscreen mode Exit fullscreen mode

Ten en cuenta que este operador sólo se debe usarse para condiciones simples que su acción sea la asignación de algún valor a una variable.

Estructuras repetitivas

6. Bucle While

El bucle While se utiliza para repetir un bloque de código mientras una condición sea verdadera. Es ideal cuando no sabes cuántas veces necesitas repetir el ciclo porque la condición se evalúa antes de cada iteración.

Imagen de un diagrama de flujo con una estructura repetitiva while

Imagina que en una aplicación de streaming de películas y series, necesitas verificar continuamente si hay una nueva recomendación para el usuario mientras está viendo contenido.

while (!usuario.TerminoDeVerPelicula)
{
    var nuevaRecomendacion = ObtenerSiguienteRecomendacion();
    MostrarRecomendacion(nuevaRecomendacion);
}
Enter fullscreen mode Exit fullscreen mode

En este ejemplo, el bucle while sigue mostrando recomendaciones al usuario hasta que termine de ver la película.

Evita modificar variables externas dentro del bucle que podrían cambiar la lógica de control inesperadamente. A esto se le conoce como "efecto secundario".

7. Bucle Do While

La estructura Do While es similar al While, pero con una diferencia clave: siempre ejecuta el bloque de código al menos una vez antes de verificar la condición. Es útil cuando deseas que el código se ejecute al menos una vez sin importar la condición inicial.

Imagen de un diagrama de flujo con una estructura repetitiva do while

Siguiendo con el ejemplo de la aplicación de streaming, imagina que quieres mostrar un resumen de los episodios de una serie, y si o si necesitas que se muestre el primero.

do
{
    MostrarResumen(episodio);
    episodio = ObtenerSiguienteEpisodio();
} while (episodio != null);
Enter fullscreen mode Exit fullscreen mode

En este caso, el bucle do while muestra un resumen del episodio actual y luego obtiene el siguiente episodio. Esto se repite hasta que no haya más episodios disponibles.

8. Bucle For

El bucle For es ideal para situaciones en las que conoces de antemano cuántas veces quieres repetir un bloque de código. Se usa comúnmente para iterar sobre una secuencia de números o índices.

Imagen de un diagrama de flujo con una estructura repetitiva for

Por ejemplo, en tu aplicación de streaming, podrías usar un bucle for para mostrar los primeros 5 trailers más populares para el usuario.

for (int i = 0; i < 5; i++)
{
    MostrarTrailer(listaDeTrailers[i]);
}
Enter fullscreen mode Exit fullscreen mode

Aquí, el bucle for se ejecuta cinco veces, mostrando los trailers de la lista en el orden de popularidad.

Siempre debes asegurarte que exista el indice (nuestra variable i) al que accedes. Por ejemplo, si esa lista de trailers solo tuviera 4 elementos, al acceder al 5to obtendríamos un error.

9. Bucle Foreach

Por último el bucle Foreach se utiliza para iterar a través de colecciones como listas o arreglos de manera sencilla. Es ideal cuando quieres recorrer todos los elementos de una colección sin preocuparte por los índices.

Imagen de un diagrama de flujo con una estructura repetitiva foreach

Por ejemplo, en el caso anterior sólo queriamos recorrer 5 elementos, pero si quisieramos recorrer todos los trailers, el foreach sería el indicado.

foreach (var trailer in listaDeTrailers)
{
    MostrarTrailer(trailer);
}
Enter fullscreen mode Exit fullscreen mode

Esto es una herramienta poderosa para simplificar el código y evitar errores de índice. Sin embargo, ten en cuenta que no puedes modificar la colección original dentro del bucle, es decir "listaDeTrailers". Para ese tipo de cambios, es mejor usar un bucle for.

Asegurate de que toda estructura repetitiva o bucle cumpla con la condición para finalizar, así no tienes un bucle infinito que genere el famoso StackOverflowException o algún otro.

Así que ahí lo tienes, ¡una inmersión completa al mundo de la lógica de programación utilizando C#!

Puedes poner en práctica tu lógica de programación en plataformas como Codewars o Hackerrank. Te recomiendo empezar con la lógica de resolver el problema antes de pensar en como hacer un código limpio. Una vez que tengas la lógica funcionando, piensa en como puedes optimizarlo.

¿Quién diría que unos simples "if", "while" y "for" podrían ser tan poderosos? Pero recuerda, con gran poder viene gran responsabilidad... ¡y también muchos errores de compilación! 😅

¡Happing coding! 🚀

Top comments (0)