En el Módulo 1 aprendiste a declarar variables, a trabajar con arrays y a manipular cadenas de texto, pero todo el código que escribiste hasta ahora se ejecutaba siempre de la misma forma, línea tras línea, sin margen para reaccionar a los datos. En la vida real, BiblioTechConsola necesita tomar decisiones: ¿puede prestarse este libro? ¿el socio ya tiene demasiados préstamos activos? ¿el ISBN introducido tiene un formato válido? Esta lección presenta las sentencias condicionales, el mecanismo con el que un programa en C# decide qué camino seguir según se cumplan o no ciertas condiciones. Es, junto con los bucles que verás en la siguiente lección, la base de cualquier lógica de negocio real.
Contenido
- La sentencia
if else ifyelse: encadenar condiciones- Operadores de comparación
- Operadores lógicos:
&&,||,! - El operador ternario
?: - Anidamiento de condicionales y buenas prácticas
- Coalescencia nula en condiciones:
??y??= - Aplicación completa: ¿se puede prestar el libro?
- La sentencia
if
ifLa sentencia if evalúa una expresión booleana (true o false) y ejecuta un bloque de
código únicamente si esa expresión es true.
bool disponible = true;
if (disponible)
{
Console.WriteLine("El libro esta disponible para prestamo.");
}Puntos clave:
- La condición va entre paréntesis
( )y debe ser una expresión de tipobool. - El bloque de código va entre llaves
{ }. Si el bloque tiene una sola instrucción, las llaves son opcionales, pero se recomienda mantenerlas siempre: mejora la legibilidad y evita errores cuando más adelante se añade una segunda línea al bloque. - Si la condición es
false, el bloque simplemente se salta y el programa continúa por la siguiente instrucción.
int paginas = 350;
// Sin llaves: funciona, pero no es recomendable
if (paginas > 300)
Console.WriteLine("Es un libro extenso.");
else if y else: encadenar condiciones
else if y else: encadenar condicionesCuando hay más de dos caminos posibles, se encadenan condiciones con else if, y se reserva
else para el caso "en cualquier otra situación".
int prestamosActivosSocio = 3;
if (prestamosActivosSocio == 0)
{
Console.WriteLine("El socio no tiene prestamos activos.");
}
else if (prestamosActivosSocio < 5)
{
Console.WriteLine("El socio tiene margen para pedir mas libros.");
}
else
{
Console.WriteLine("El socio ha alcanzado el limite de prestamos.");
}El flujo se evalúa de arriba a abajo y se detiene en la primera condición que sea true.
Esto es importante: aunque prestamosActivosSocio < 5 también sería cierto cuando vale 0, la
primera condición (== 0) ya ha capturado ese caso, así que el resto de bloques else if
ni siquiera se evalúan.
| Estructura | ¿Cuántos bloques se ejecutan? | ¿Cuándo usarla? |
|---|---|---|
if solo |
0 o 1 | Una única condición opcional |
if/else |
Siempre 1 | Dos caminos excluyentes |
if/else if/else |
Siempre 1 (el primero que cumpla) | Varios caminos excluyentes, ordenados por prioridad |
- Operadores de comparación
Para construir condiciones se necesitan operadores que comparen valores y devuelvan un
bool.
| Operador | Significado | Ejemplo (paginas = 350) |
Resultado |
|---|---|---|---|
== |
Igual a | paginas == 350 |
true |
!= |
Distinto de | paginas != 350 |
false |
> |
Mayor que | paginas > 300 |
true |
< |
Menor que | paginas < 300 |
false |
>= |
Mayor o igual que | paginas >= 350 |
true |
<= |
Menor o igual que | paginas <= 349 |
false |
Un error muy habitual entre quienes empiezan es confundir = (asignación) con ==
(comparación). if (disponible = true) no compara nada: asigna true a disponible y,
además, no compila si disponible no es de tipo bool compatible con esa asignación en ese
contexto. Presta siempre atención a este detalle.
También se pueden comparar cadenas de texto con ==, ya que string sobrecarga ese operador
para comparar el contenido (y no la referencia en memoria):
string tituloBuscado = "Rayuela";
string tituloCatalogo = "Rayuela";
if (tituloBuscado == tituloCatalogo)
{
Console.WriteLine("Coincidencia encontrada en el catalogo.");
}
- Operadores lógicos:
&&, ||, !
&&, ||, !Cuando una decisión depende de varias condiciones a la vez, se combinan con operadores lógicos.
| Operador | Nombre | Se cumple cuando... |
|---|---|---|
&& |
Y lógico (AND) | ambas condiciones son true |
| ` | ` | |
! |
Negación (NOT) | invierte el valor de la condición |
bool disponible = true;
int prestamosActivosSocio = 2;
const int LimitePrestamos = 5;
if (disponible && prestamosActivosSocio < LimitePrestamos)
{
Console.WriteLine("Prestamo autorizado.");
}
else
{
Console.WriteLine("Prestamo denegado.");
}Con ! se invierte una condición booleana, lo que a menudo hace el código más legible que
comparar explícitamente con false:
bool esMoroso = false;
if (!esMoroso)
{
Console.WriteLine("El socio no tiene sanciones pendientes.");
}Un detalle importante de rendimiento y de seguridad es el cortocircuito (short-circuit
evaluation): en a && b, si a ya es false, C# no llega a evaluar b porque el resultado
ya está decidido. Lo mismo ocurre con a || b si a ya es true. Esto permite escribir
condiciones seguras como la siguiente, donde la segunda parte solo se evalúa si la primera
garantiza que no habrá un error:
string[] titulosLibros = { "Cien anos de soledad", "Rayuela", "Ficciones" };
int indice = 5;
if (indice < titulosLibros.Length && titulosLibros[indice] == "Rayuela")
{
Console.WriteLine("Encontrado.");
}
else
{
Console.WriteLine("Indice fuera de rango o titulo distinto.");
}Si indice < titulosLibros.Length es false (como en este caso, con solo 3 elementos y un
índice de valor 5), C# nunca llega a acceder a titulosLibros[indice], evitando así una
excepción por índice fuera de rango.
- El operador ternario
?:
?:El operador ternario condensa un if/else sencillo, de una sola expresión, en una única
línea. Su forma es:
bool disponible = true;
string estado = disponible ? "Disponible" : "Prestado";
Console.WriteLine($"Estado del libro: {estado}");Es equivalente a:
El ternario es ideal cuando el resultado es un valor simple que se va a asignar o a mostrar directamente. No conviene abusar de él para lógica compleja ni anidar varios ternarios entre sí, porque el código se vuelve difícil de leer:
// Evita esto: dos ternarios anidados son dificiles de leer de un vistazo
string categoria = paginas > 500 ? "Extenso" : paginas > 200 ? "Medio" : "Breve";En esos casos es preferible un if/else if/else explícito, o el switch que verás en la
próxima lección de este módulo.
- Anidamiento de condicionales y buenas prácticas
Es habitual necesitar una condición dentro de otra:
bool disponible = true;
int prestamosActivosSocio = 4;
const int LimitePrestamos = 5;
if (disponible)
{
if (prestamosActivosSocio < LimitePrestamos)
{
Console.WriteLine("Prestamo autorizado.");
}
else
{
Console.WriteLine("El socio ha alcanzado su limite de prestamos.");
}
}
else
{
Console.WriteLine("El libro no esta disponible actualmente.");
}Este código funciona, pero cuando el anidamiento crece (tres, cuatro niveles) se vuelve difícil de seguir. Dos técnicas ayudan a mantenerlo controlado:
Combinar condiciones con operadores lógicos en lugar de anidar, cuando el resultado final es el mismo:
if (disponible && prestamosActivosSocio < LimitePrestamos)
{
Console.WriteLine("Prestamo autorizado.");
}
else
{
Console.WriteLine("Prestamo denegado.");
}Invertir la condición y salir cuanto antes (early return o guard clauses), muy útil
dentro de métodos o funciones locales: en lugar de anidar el caso "bueno" dentro de varios
if, se descartan primero los casos que impiden continuar.
string EvaluarPrestamo(bool disponible, int prestamosActivosSocio, int limitePrestamos)
{
if (!disponible)
{
return "El libro no esta disponible.";
}
if (prestamosActivosSocio >= limitePrestamos)
{
return "El socio ha alcanzado su limite de prestamos.";
}
return "Prestamo autorizado.";
}Esta segunda versión evita el anidamiento por completo y cada condición se lee de forma independiente, lo que facilita añadir nuevas reglas en el futuro (por ejemplo, comprobar si el socio tiene sanciones pendientes) sin reestructurar todo el bloque.
- Coalescencia nula en condiciones:
?? y ??=
?? y ??=En la lección de variables ya viste que un tipo de referencia, como string, puede valer
null. Los operadores ?? (coalescencia nula) y ??= (asignación con coalescencia nula) son
muy útiles para tomar decisiones cuando un dato puede faltar.
?? devuelve el operando izquierdo si no es null, o el derecho en caso contrario:
string? isbnIntroducido = null;
string isbnAMostrar = isbnIntroducido ?? "ISBN no disponible";
Console.WriteLine(isbnAMostrar); // ISBN no disponibleEsto evita tener que escribir el equivalente más largo:
string isbnAMostrar;
if (isbnIntroducido != null)
{
isbnAMostrar = isbnIntroducido;
}
else
{
isbnAMostrar = "ISBN no disponible";
}??= asigna un valor por defecto solo si la variable actualmente es null, y no hace
nada si ya tiene un valor:
string? notaSocio = null;
notaSocio ??= "Sin incidencias registradas";
Console.WriteLine(notaSocio); // Sin incidencias registradas
notaSocio ??= "Este texto nunca se asigna";
Console.WriteLine(notaSocio); // Sigue mostrando: Sin incidencias registradasEstos operadores también se combinan directamente dentro de una condición if:
string? busquedaUsuario = null;
if ((busquedaUsuario ?? "").Length > 0)
{
Console.WriteLine("Buscando: " + busquedaUsuario);
}
else
{
Console.WriteLine("No se ha introducido ningun termino de busqueda.");
}
- Aplicación completa: ¿se puede prestar el libro?
Reunamos todo lo anterior en un ejemplo cercano a lo que tendrá BiblioTechConsola: decidir si un libro puede prestarse según su disponibilidad y el número de préstamos activos del socio.
bool libroDisponible = true;
int prestamosActivosSocio = 4;
const int LimitePrestamosPorSocio = 5;
bool socioSancionado = false;
bool sePuedePrestar = libroDisponible
&& !socioSancionado
&& prestamosActivosSocio < LimitePrestamosPorSocio;
string mensaje = sePuedePrestar
? "Prestamo autorizado: puedes entregar el ejemplar."
: "Prestamo denegado.";
Console.WriteLine(mensaje);
if (!sePuedePrestar)
{
if (!libroDisponible)
{
Console.WriteLine("Motivo: no quedan ejemplares disponibles.");
}
else if (socioSancionado)
{
Console.WriteLine("Motivo: el socio tiene una sancion activa.");
}
else
{
Console.WriteLine("Motivo: el socio alcanzo el limite de prestamos.");
}
}Fíjate en el diseño: una única expresión booleana (sePuedePrestar) concentra la regla de
negocio principal combinando && y !, el ternario decide el mensaje principal, y solo si el
préstamo se deniega se entra en un segundo bloque if/else if/else para explicar el
motivo exacto. Es una estructura mucho más mantenible que anidar los tres if unos dentro de
otros.
Errores Comunes y Consejos
- Confundir
=con==. Es el error más frecuente entre principiantes. El compilador de C# suele detectarlo si los tipos no encajan, pero conviene revisarlo siempre a simple vista. - Anidar demasiados niveles de
if. Si te encuentras con tres o más niveles de indentación, casi siempre se puede simplificar combinando condiciones con&&/||o aplicando el patrón de salida anticipada (guard clauses). - Olvidar el
elsecuando realmente hace falta. Si una variable debe tener siempre un valor asignado, asegúrate de cubrir todos los caminos posibles. - Abusar del operador ternario para lógica compleja o anidada. Resérvalo para decisiones simples de un único valor.
- No comprobar
nullantes de operar sobre una variable de tipo referencia. Usa??para dar un valor por defecto en lugar de arriesgarte a una excepciónNullReferenceException(verás las excepciones en detalle en la última lección de este módulo). - Comparar cadenas sin tener en cuenta mayúsculas/minúsculas cuando el usuario introduce
texto libre. Recuerda
ToLower()(visto en la lección anterior) si quieres una comparación que ignore la capitalización.
Ejercicios
-
Declara tres variables:
int paginas,bool disponibleyint prestamosActivosSocio. Escribe unif/else if/elseque muestre por consola:"No disponible"sidisponibleesfalse."Prestamo largo (mas de 400 paginas)"si está disponible ypaginas > 400."Prestamo normal"en cualquier otro caso en que esté disponible.
-
Usando el operador ternario, crea una variable
string resultadoque contenga"Socio al limite"siprestamosActivosSocio >= 5, o"Socio con margen"en caso contrario. Muestra el resultado por consola. -
Declara
string? emailSocio = null;. Usa??para mostrar por consola el email si existe, o el texto"Sin email registrado"si esnull. Después usa??=para asignarle el valor"[email protected]"solo si sigue siendonull, y muestra el valor final.
Soluciones
int paginas = 550;
bool disponible = true;
int prestamosActivosSocio = 2;
if (!disponible)
{
Console.WriteLine("No disponible");
}
else if (paginas > 400)
{
Console.WriteLine("Prestamo largo (mas de 400 paginas)");
}
else
{
Console.WriteLine("Prestamo normal");
}
Con paginas = 550 y disponible = true, el resultado mostrado es
"Prestamo largo (mas de 400 paginas)". Observa que se comprueba primero !disponible:
así, si el libro no estuviera disponible, ni siquiera se llegaría a mirar el número de
páginas.
int prestamosActivosSocio = 5;
string resultado = prestamosActivosSocio >= 5 ? "Socio al limite" : "Socio con margen";
Console.WriteLine(resultado);
Con prestamosActivosSocio = 5, el resultado mostrado es "Socio al limite", ya que la
condición >= 5 se cumple exactamente en el límite.
string? emailSocio = null;
string emailAMostrar = emailSocio ?? "Sin email registrado";
Console.WriteLine(emailAMostrar); // Sin email registrado
emailSocio ??= "[email protected]";
Console.WriteLine(emailSocio); // [email protected]
La primera línea no modifica emailSocio: solo calcula un valor alternativo para
mostrarlo. La segunda línea (??=) sí modifica la variable, asignándole el valor por
defecto porque en ese momento seguía siendo null.
Conclusión
En esta lección has aprendido a tomar decisiones en tu código con if/else if/else, a
construir condiciones con operadores de comparación y lógicos, a simplificar asignaciones
sencillas con el operador ternario ?:, a mantener el anidamiento bajo control combinando
condiciones o aplicando salidas anticipadas, y a usar ??/??= para trabajar con datos que
pueden faltar. Con esto, BiblioTechConsola ya puede decidir si un préstamo es válido según
varias reglas de negocio a la vez.
Sin embargo, tomar una única decisión no es suficiente cuando hay que repetir una acción
muchas veces: recorrer todo el catálogo de libros, contar cuántos están disponibles, o buscar
uno por título hasta encontrarlo. En la siguiente lección, Bucles, aprenderás a repetir
instrucciones con for, while, do-while y foreach, y a controlar ese repetición con
break y continue.
Curso de Programación en C#
Módulo 1: Introducción a C#
- Introducción a C#
- Configuración del Entorno de Desarrollo
- Programa Hola Mundo
- Sintaxis y Estructura Básica
- Variables y Tipos de Datos
- Arrays y Cadenas de Texto
Módulo 2: Estructuras de Control
Módulo 3: Programación Orientada a Objetos
- Clases y Objetos
- Métodos
- Constructores y Destructores
- Herencia
- Polimorfismo
- Encapsulamiento
- Abstracción
- Structs y Records: Tipos por Valor y por Referencia
Módulo 4: Conceptos Avanzados de C#
- Interfaces
- Delegados y Eventos
- Pattern Matching y Características Modernas de C#
- Genéricos
- Colecciones
- LINQ (Consulta Integrada en el Lenguaje)
- Programación Asíncrona
Módulo 5: Trabajando con Datos
- Entrada/Salida de Archivos
- Serialización
- Conectividad con Bases de Datos
- Entity Framework
- Trabajo con JSON y Consumo de APIs REST
Módulo 6: Temas Avanzados
- Reflexión
- Atributos
- Programación Dinámica
- Gestión de Memoria y Recolección de Basura
- Multihilo y Programación Paralela
Módulo 7: Construcción de Aplicaciones
- Formularios de Windows
- WPF (Windows Presentation Foundation)
- ASP.NET Core
- Blazor
- Xamarin y .NET MAUI
Módulo 8: Mejores Prácticas y Patrones de Diseño
- Estándares de Codificación y Mejores Prácticas
- Patrones de Diseño
- Inyección de Dependencias e Inversión de Control
- Pruebas Unitarias
- Revisión y Refactorización de Código
