En el Mòdul 1 vas aprendre a declarar variables, a treballar amb arrays i a manipular cadenes de text, però tot el codi que vas escriure fins ara s'executava sempre de la mateixa manera, línia rere línia, sense marge per reaccionar a les dades. A la vida real, BiblioTechConsola necessita prendre decisions: es pot deixar aquest llibre? el soci ja té massa préstecs actius? l'ISBN introduït té un format vàlid? Aquesta lliçó presenta les sentències condicionals, el mecanisme amb què un programa en C# decideix quin camí seguir segons es compleixin o no certes condicions. És, juntament amb els bucles que veuràs a la lliçó següent, la base de qualsevol lògica de negoci real.
Contingut
- La sentència
if else ifielse: encadenar condicions- Operadors de comparació
- Operadors lògics:
&&,||,! - L'operador ternari
?: - Imbricació de condicionals i bones pràctiques
- Coalescència nul·la en condicions:
??i??= - Aplicació completa: es pot deixar el llibre?
- La sentència
if
ifLa sentència if avalua una expressió booleana (true o false) i executa un bloc de codi
únicament si aquesta expressió és true.
bool disponible = true;
if (disponible)
{
Console.WriteLine("El llibre esta disponible per prestar.");
}Punts clau:
- La condició va entre parèntesis
( )i ha de ser una expressió de tipusbool. - El bloc de codi va entre claus
{ }. Si el bloc té una única instrucció, les claus són opcionals, però es recomana mantenir-les sempre: millora la llegibilitat i evita errors quan més endavant s'afegeix una segona línia al bloc. - Si la condició és
false, el bloc simplement se salta i el programa continua per la instrucció següent.
int pagines = 350;
// Sense claus: funciona, pero no es recomanable
if (pagines > 300)
Console.WriteLine("Es un llibre extens.");
else if i else: encadenar condicions
else if i else: encadenar condicionsQuan hi ha més de dos camins possibles, s'encadenen condicions amb else if, i es reserva
else per al cas "en qualsevol altra situació".
int prestecsActiusSoci = 3;
if (prestecsActiusSoci == 0)
{
Console.WriteLine("El soci no te prestecs actius.");
}
else if (prestecsActiusSoci < 5)
{
Console.WriteLine("El soci te marge per demanar mes llibres.");
}
else
{
Console.WriteLine("El soci ha arribat al limit de prestecs.");
}El flux s'avalua de dalt a baix i s'atura en la primera condició que sigui true. Això és
important: encara que prestecsActiusSoci < 5 també seria certa quan val 0, la primera
condició (== 0) ja ha capturat aquest cas, així que la resta de blocs else if ni tan sols
s'avaluen.
| Estructura | Quants blocs s'executen? | Quan usar-la? |
|---|---|---|
if sol |
0 o 1 | Una única condició opcional |
if/else |
Sempre 1 | Dos camins excloents |
if/else if/else |
Sempre 1 (el primer que compleixi) | Diversos camins excloents, ordenats per prioritat |
- Operadors de comparació
Per construir condicions calen operadors que comparin valors i retornin un bool.
| Operador | Significat | Exemple (pagines = 350) |
Resultat |
|---|---|---|---|
== |
Igual a | pagines == 350 |
true |
!= |
Diferent de | pagines != 350 |
false |
> |
Més gran que | pagines > 300 |
true |
< |
Més petit que | pagines < 300 |
false |
>= |
Més gran o igual que | pagines >= 350 |
true |
<= |
Més petit o igual que | pagines <= 349 |
false |
Un error molt habitual entre qui comença és confondre = (assignació) amb == (comparació).
if (disponible = true) no compara res: assigna true a disponible i, a més, no compila si
disponible no és d'un tipus bool compatible amb aquesta assignació en aquest context. Para
sempre atenció a aquest detall.
També es poden comparar cadenes de text amb ==, ja que string sobrecarrega aquest operador
per comparar el contingut (i no la referència en memòria):
string titolBuscat = "Rayuela";
string titolCataleg = "Rayuela";
if (titolBuscat == titolCataleg)
{
Console.WriteLine("Coincidencia trobada al cataleg.");
}
- Operadors lògics:
&&, ||, !
&&, ||, !Quan una decisió depèn de diverses condicions alhora, es combinen amb operadors lògics.
| Operador | Nom | Es compleix quan... |
|---|---|---|
&& |
I lògic (AND) | ambdues condicions són true |
|| |
O lògic (OR) | almenys una de les condicions és true |
! |
Negació (NOT) | inverteix el valor de la condició |
bool disponible = true;
int prestecsActiusSoci = 2;
const int LimitPrestecs = 5;
if (disponible && prestecsActiusSoci < LimitPrestecs)
{
Console.WriteLine("Prestec autoritzat.");
}
else
{
Console.WriteLine("Prestec denegat.");
}Amb ! s'inverteix una condició booleana, cosa que sovint fa el codi més llegible que comparar
explícitament amb false:
Un detall important de rendiment i de seguretat és el curtcircuit (short-circuit
evaluation): a a && b, si a ja és false, C# no arriba a avaluar b perquè el resultat ja
està decidit. El mateix passa amb a || b si a ja és true. Això permet escriure condicions
segures com la següent, on la segona part només s'avalua si la primera garanteix que no hi haurà
un error:
string[] titolsLlibres = { "Cent anys de solitud", "Rayuela", "Ficcions" };
int index = 5;
if (index < titolsLlibres.Length && titolsLlibres[index] == "Rayuela")
{
Console.WriteLine("Trobat.");
}
else
{
Console.WriteLine("Index fora de rang o titol diferent.");
}Si index < titolsLlibres.Length és false (com en aquest cas, amb només 3 elements i un
index de valor 5), C# mai arriba a accedir a titolsLlibres[index], evitant així una excepció
per índex fora de rang.
- L'operador ternari
?:
?:L'operador ternari condensa un if/else senzill, d'una sola expressió, en una única línia.
La seva forma és:
bool disponible = true;
string estat = disponible ? "Disponible" : "Prestat";
Console.WriteLine($"Estat del llibre: {estat}");És equivalent a:
El ternari és ideal quan el resultat és un valor simple que s'assignarà o es mostrarà directament. No convé abusar-ne per a lògica complexa ni imbricar diversos ternaris entre si, perquè el codi es torna difícil de llegir:
// Evita aixo: dos ternaris imbricats son dificils de llegir d'un cop d'ull
string categoria = pagines > 500 ? "Extens" : pagines > 200 ? "Mitja" : "Breu";En aquests casos és preferible un if/else if/else explícit, o el switch que veuràs a la
propera lliçó d'aquest mòdul.
- Imbricació de condicionals i bones pràctiques
És habitual necessitar una condició dins d'una altra:
bool disponible = true;
int prestecsActiusSoci = 4;
const int LimitPrestecs = 5;
if (disponible)
{
if (prestecsActiusSoci < LimitPrestecs)
{
Console.WriteLine("Prestec autoritzat.");
}
else
{
Console.WriteLine("El soci ha arribat al seu limit de prestecs.");
}
}
else
{
Console.WriteLine("El llibre no esta disponible actualment.");
}Aquest codi funciona, però quan la imbricació creix (tres, quatre nivells) es torna difícil de seguir. Dues tècniques ajuden a mantenir-lo controlat:
Combinar condicions amb operadors lògics en lloc d'imbricar, quan el resultat final és el mateix:
if (disponible && prestecsActiusSoci < LimitPrestecs)
{
Console.WriteLine("Prestec autoritzat.");
}
else
{
Console.WriteLine("Prestec denegat.");
}Invertir la condició i sortir com abans millor (early return o guard clauses), molt
útil dins de mètodes o funcions locals: en lloc d'imbricar el cas "bo" dins de diversos if,
es descarten primer els casos que impedeixen continuar.
string AvaluarPrestec(bool disponible, int prestecsActiusSoci, int limitPrestecs)
{
if (!disponible)
{
return "El llibre no esta disponible.";
}
if (prestecsActiusSoci >= limitPrestecs)
{
return "El soci ha arribat al seu limit de prestecs.";
}
return "Prestec autoritzat.";
}Aquesta segona versió evita la imbricació per complet i cada condició es llegeix de manera independent, cosa que facilita afegir noves regles en el futur (per exemple, comprovar si el soci té sancions pendents) sense reestructurar tot el bloc.
- Coalescència nul·la en condicions:
?? i ??=
?? i ??=A la lliçó de variables ja vas veure que un tipus de referència, com string, pot valer
null. Els operadors ?? (coalescència nul·la) i ??= (assignació amb coalescència nul·la)
són molt útils per prendre decisions quan una dada pot faltar.
?? retorna l'operand esquerre si no és null, o el dret en cas contrari:
string? isbnIntroduit = null;
string isbnAMostrar = isbnIntroduit ?? "ISBN no disponible";
Console.WriteLine(isbnAMostrar); // ISBN no disponibleAixò evita haver d'escriure l'equivalent més llarg:
string isbnAMostrar;
if (isbnIntroduit != null)
{
isbnAMostrar = isbnIntroduit;
}
else
{
isbnAMostrar = "ISBN no disponible";
}??= assigna un valor per defecte només si la variable actualment és null, i no fa res
si ja té un valor:
string? notaSoci = null;
notaSoci ??= "Sense incidencies registrades";
Console.WriteLine(notaSoci); // Sense incidencies registrades
notaSoci ??= "Aquest text mai s'assigna";
Console.WriteLine(notaSoci); // Continua mostrant: Sense incidencies registradesAquests operadors també es combinen directament dins d'una condició if:
string? cercaUsuari = null;
if ((cercaUsuari ?? "").Length > 0)
{
Console.WriteLine("Cercant: " + cercaUsuari);
}
else
{
Console.WriteLine("No hi ha cap terme de cerca introduit.");
}
- Aplicació completa: es pot deixar el llibre?
Reunim tot l'anterior en un exemple proper al que tindrà BiblioTechConsola: decidir si un llibre es pot deixar segons la seva disponibilitat i el nombre de préstecs actius del soci.
bool llibreDisponible = true;
int prestecsActiusSoci = 4;
const int LimitPrestecsPerSoci = 5;
bool sociSancionat = false;
bool esPotPrestar = llibreDisponible
&& !sociSancionat
&& prestecsActiusSoci < LimitPrestecsPerSoci;
string missatge = esPotPrestar
? "Prestec autoritzat: pots lliurar aquest exemplar."
: "Prestec denegat.";
Console.WriteLine(missatge);
if (!esPotPrestar)
{
if (!llibreDisponible)
{
Console.WriteLine("Motiu: no queden exemplars disponibles.");
}
else if (sociSancionat)
{
Console.WriteLine("Motiu: el soci te una sancio activa.");
}
else
{
Console.WriteLine("Motiu: el soci va arribar al limit de prestecs.");
}
}Fixa't en el disseny: una única expressió booleana (esPotPrestar) concentra la regla de
negoci principal combinant && i !, el ternari decideix el missatge principal, i només si el
préstec es denega s'entra en un segon bloc if/else if/else per explicar el motiu exacte.
És una estructura molt més mantenible que imbricar els tres if un dins de l'altre.
Errors Comuns i Consells
- Confondre
=amb==. És l'error més freqüent entre principiants. El compilador de C# sol detectar-ho si els tipus no encaixen, però convé revisar-ho sempre a simple vista. - Imbricar massa nivells d'
if. Si et trobes amb tres o més nivells d'indentació, gairebé sempre es pot simplificar combinant condicions amb&&/||o aplicant el patró de sortida anticipada (guard clauses). - Oblidar l'
elsequan realment fa falta. Si una variable ha de tenir sempre un valor assignat, assegura't de cobrir tots els camins possibles. - Abusar de l'operador ternari per a lògica complexa o imbricada. Reserva'l per a decisions simples d'un únic valor.
- No comprovar
nullabans d'operar sobre una variable de tipus referència. Fes servir??per donar un valor per defecte en lloc d'arriscar-te a una excepcióNullReferenceException(veuràs les excepcions en detall a l'última lliçó d'aquest mòdul). - Comparar cadenes sense tenir en compte majúscules/minúscules quan l'usuari introdueix
text lliure. Recorda
ToLower()(vist a la lliçó anterior) si vols una comparació que ignori la capitalització.
Exercicis
-
Declara tres variables:
int pagines,bool disponibleiint prestecsActiusSoci. Escriu unif/else if/elseque mostri per consola:"No disponible"sidisponibleésfalse."Prestec llarg (mes de 400 pagines)"si esta disponible ipagines > 400."Prestec normal"en qualsevol altre cas en que estigui disponible.
-
Fent servir l'operador ternari, crea una variable
string resultatque contingui"Soci al limit"siprestecsActiusSoci >= 5, o"Soci amb marge"en cas contrari. Mostra el resultat per consola. -
Declara
string? correuSoci = null;. Fes servir??per mostrar per consola el correu si existeix, o el text"Sense correu registrat"si ésnull. Després fes servir??=per assignar-li el valor"[email protected]"només si continua sentnull, i mostra el valor final.
Solucions
int pagines = 550;
bool disponible = true;
int prestecsActiusSoci = 2;
if (!disponible)
{
Console.WriteLine("No disponible");
}
else if (pagines > 400)
{
Console.WriteLine("Prestec llarg (mes de 400 pagines)");
}
else
{
Console.WriteLine("Prestec normal");
}
Amb pagines = 550 i disponible = true, el resultat mostrat és
"Prestec llarg (mes de 400 pagines)". Fixa't que primer es comprova !disponible: així,
si el llibre no estigués disponible, ni tan sols s'arribaria a mirar el nombre de pàgines.
int prestecsActiusSoci = 5;
string resultat = prestecsActiusSoci >= 5 ? "Soci al limit" : "Soci amb marge";
Console.WriteLine(resultat);
Amb prestecsActiusSoci = 5, el resultat mostrat és "Soci al limit", ja que la condició
>= 5 es compleix exactament al límit.
string? correuSoci = null;
string correuAMostrar = correuSoci ?? "Sense correu registrat";
Console.WriteLine(correuAMostrar); // Sense correu registrat
correuSoci ??= "[email protected]";
Console.WriteLine(correuSoci); // [email protected]
La primera línia no modifica correuSoci: només calcula un valor alternatiu per
mostrar-lo. La segona línia (??=) sí que modifica la variable, assignant-li el valor per
defecte perquè en aquell moment continuava sent null.
Conclusió
En aquesta lliçó has après a prendre decisions al teu codi amb if/else if/else, a
construir condicions amb operadors de comparació i lògics, a simplificar assignacions senzilles
amb l'operador ternari ?:, a mantenir la imbricació sota control combinant condicions o
aplicant sortides anticipades, i a fer servir ??/??= per treballar amb dades que poden
faltar. Amb això, BiblioTechConsola ja pot decidir si un préstec és vàlid segons diverses
regles de negoci alhora.
Tanmateix, prendre una única decisió no és suficient quan cal repetir una acció moltes
vegades: recórrer tot el catàleg de llibres, comptar quants estan disponibles, o buscar-ne un
pel títol fins a trobar-lo. A la lliçó següent, Bucles, aprendràs a repetir instruccions
amb for, while, do-while i foreach, i a controlar aquesta repetició amb break i
continue.
Curs de Programació en C#
Mòdul 1: Introducció al C#
- Introducció al C#
- Configuració de l'Entorn de Desenvolupament
- Programa Hola Món
- Sintaxi i Estructura Bàsica
- Variables i Tipus de Dades
- Arrays i Cadenes de Text
Mòdul 2: Estructures de Control
Mòdul 3: Programació Orientada a Objectes
- Classes i Objectes
- Mètodes
- Constructors i Destructors
- Herència
- Polimorfisme
- Encapsulació
- Abstracció
- Structs i Records: Tipus per Valor i per Referència
Mòdul 4: Conceptes Avançats de C#
- Interfícies
- Delegats i Esdeveniments
- Pattern Matching i Característiques Modernes de C#
- Genèrics
- Col·leccions
- LINQ (Consulta Integrada en el Llenguatge)
- Programació Asíncrona
Mòdul 5: Treballant amb Dades
- Entrada/Sortida de Fitxers
- Serialització
- Connectivitat amb Bases de Dades
- Entity Framework
- Treball amb JSON i Consum d'APIs REST
Mòdul 6: Temes Avançats
- Reflexió
- Atributs
- Programació Dinàmica
- Gestió de Memòria i Recollida d'Escombraries
- Multifil i Programació Paral·lela
Mòdul 7: Construcció d'Aplicacions
Mòdul 8: Bones Pràctiques i Patrons de Disseny
- Estàndards de Codificació i Bones Pràctiques
- Patrons de Disseny
- Injecció de Dependències i Inversió de Control
- Proves Unitàries
- Revisió i Refactorització de Codi
