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

  1. La sentencia if
  2. else if y else: encadenar condiciones
  3. Operadores de comparación
  4. Operadores lógicos: &&, ||, !
  5. El operador ternario ?:
  6. Anidamiento de condicionales y buenas prácticas
  7. Coalescencia nula en condiciones: ?? y ??=
  8. Aplicación completa: ¿se puede prestar el libro?

  1. La sentencia if

La 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 tipo bool.
  • 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.");

  1. else if y else: encadenar condiciones

Cuando 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

  1. 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.");
}

  1. 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.

  1. El operador ternario ?:

El operador ternario condensa un if/else sencillo, de una sola expresión, en una única línea. Su forma es:

condicion ? valorSiVerdadero : valorSiFalso
bool disponible = true;
string estado = disponible ? "Disponible" : "Prestado";

Console.WriteLine($"Estado del libro: {estado}");

Es equivalente a:

string estado;
if (disponible)
{
    estado = "Disponible";
}
else
{
    estado = "Prestado";
}

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.

  1. 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.

  1. Coalescencia nula en condiciones: ?? 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 disponible

Esto 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 registradas

Estos 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.");
}

  1. 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 else cuando 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 null antes de operar sobre una variable de tipo referencia. Usa ?? para dar un valor por defecto en lugar de arriesgarte a una excepción NullReferenceException (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

  1. Declara tres variables: int paginas, bool disponible y int prestamosActivosSocio. Escribe un if/else if/else que muestre por consola:

    • "No disponible" si disponible es false.
    • "Prestamo largo (mas de 400 paginas)" si está disponible y paginas > 400.
    • "Prestamo normal" en cualquier otro caso en que esté disponible.
  2. Usando el operador ternario, crea una variable string resultado que contenga "Socio al limite" si prestamosActivosSocio >= 5, o "Socio con margen" en caso contrario. Muestra el resultado por consola.

  3. Declara string? emailSocio = null;. Usa ?? para mostrar por consola el email si existe, o el texto "Sin email registrado" si es null. Después usa ??= para asignarle el valor "[email protected]" solo si sigue siendo null, 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#

Módulo 2: Estructuras de Control

Módulo 3: Programación Orientada a Objetos

Módulo 4: Conceptos Avanzados de C#

Módulo 5: Trabajando con Datos

Módulo 6: Temas Avanzados

Módulo 7: Construcción de Aplicaciones

Módulo 8: Mejores Prácticas y Patrones de Diseño

Módulo 9: Proyecto Final

© Copyright 2026. Todos los derechos reservados