A la lliçó anterior vas veure com repetir accions amb bucles; abans, vas aprendre a prendre
decisions amb if/else if/else. Tanmateix, quan una mateixa variable s'ha de comparar
contra molts valors possibles —per exemple, classificar un llibre de BiblioTech segons la
seva categoria: "Narrativa", "Assaig", "Poesia", "Infantil", "Ciència"—, encadenar else if
una vegada i una altra es torna repetitiu i difícil de llegir. La sentència switch resol
exactament aquest cas: compara una expressió contra una llista de valors possibles i executa
el bloc que coincideixi, amb una sintaxi més clara i ordenada.
Contingut
- La sentència
switchclàssica case,defaulti la importància debreak- Diversos valors per a un mateix
case switchvsif/else if/else- Una ullada al futur: switch expressions i pattern matching
- Aplicació completa: classificar un llibre per categoria
- La sentència
switch clàssica
switch clàssicaUn switch avalua una expressió una sola vegada i compara el seu resultat contra una sèrie de
valors constants, cadascun definit en una etiqueta case.
string categoria = "Narrativa";
switch (categoria)
{
case "Narrativa":
Console.WriteLine("Seccio de narrativa - Planta 1");
break;
case "Assaig":
Console.WriteLine("Seccio de no ficcio - Planta 2");
break;
case "Poesia":
Console.WriteLine("Seccio de poesia - Planta 1");
break;
default:
Console.WriteLine("Categoria no reconeguda - consulta amb el bibliotecari");
break;
}Estructura de la sentència:
switch (expressio): l'expressió s'avalua una única vegada; pot ser de tipusstring, qualsevol tipus numèric enter,char,bool, o unenum(que es veurà amb detall en mòduls posteriors).- Cada
case valor:defineix una possible coincidència. Siexpressio == valor, s'executa el bloc de codi corresponent. default:s'executa si cap delscaseanteriors coincideix. És equivalent a l'elsefinal d'una cadenaif/else if/else, i encara que tècnicament és opcional, es recomana incloure'l sempre per cobrir casos inesperats.
case, default i la importància de break
case, default i la importància de breakA diferència d'altres llenguatges, a C# cada bloc case ha d'acabar de forma explícita
—normalment amb break— abans de passar al següent. Si un case no conté cap instrucció que
acabi el bloc (break, return, throw, o continuar amb goto case), el compilador dona un
error: C# no permet el "fall-through implícit" (caure d'un case al següent sense voler-ho)
que sí que existeix en llenguatges com C o Java.
Per a l'ús quotidià, n'hi ha prou amb recordar la regla simple: tot case s'ha de tancar amb
break (o amb return si el switch és dins d'un mètode que ha de retornar un valor).
string categoria = "Comic";
switch (categoria)
{
case "Narrativa":
Console.WriteLine("Narrativa");
break;
case "Comic":
Console.WriteLine("Comic i manga");
break; // obligatori: sense aquest break, el codi no compila
default:
Console.WriteLine("Sense classificar");
break;
}| Element | Obligatori? | Funció |
|---|---|---|
switch (expr) |
Sí | Obre l'estructura i defineix què es compararà |
case valor: |
Almenys un (o default) |
Defineix un possible valor de coincidència |
break; |
Sí (per cada case amb codi) |
Acaba el bloc i surt del switch |
default: |
Recomanat, no obligatori | Cobreix qualsevol valor no contemplat als case |
- Diversos valors per a un mateix
case
caseQuan diversos valors diferents han de provocar exactament la mateixa acció, es poden "apilar"
diverses etiquetes case seguides, sense codi entre elles, abans del bloc comú:
string categoria = "Infantil";
switch (categoria)
{
case "Infantil":
case "Juvenil":
Console.WriteLine("Seccio familiar - Planta baixa");
break;
case "Narrativa":
case "Ciencia Ficcio":
case "Fantasia":
Console.WriteLine("Seccio de narrativa - Planta 1");
break;
case "Assaig":
case "Historia":
case "Ciencia":
Console.WriteLine("Seccio de no ficcio - Planta 2");
break;
default:
Console.WriteLine("Categoria no reconeguda");
break;
}Aquí, tant "Infantil" com "Juvenil" executen el mateix bloc, perquè C# permet "apilar"
etiquetes case sense break intermedi: només l'últim case del grup porta el codi i el
break. Això és diferent del fall-through prohibit: apilar etiquetes buides està permès
perquè no hi ha codi entre elles que es "salti" per error.
switch vs if/else if/else
switch vs if/else if/else| Aspecte | switch |
if/else if/else |
|---|---|---|
| Comparacions | Igualtat exacta contra valors constants | Qualsevol condició booleana, inclosos rangs |
| Llegibilitat amb molts valors | Alta: cada cas és una línia clara | Baixa: es repeteix la mateixa variable moltes vegades |
Rangs (pagines > 100 && pagines < 300) |
No directament (requereix trucs avançats) | Sí, de forma natural |
| Tipus admesos | string, enters, char, bool, enum, patrons |
Qualsevol expressió booleana |
Regla pràctica: si estàs comparant la mateixa variable contra una llista fixa de valors
concrets (categories, codis, opcions de menú), fes servir switch. Si necessites avaluar
rangs, combinacions de diverses variables, o condicions més elaborades, fes servir
if/else if/else com a la primera lliçó d'aquest mòdul.
- Una ullada al futur: switch expressions i pattern matching
El switch clàssic que has vist en aquesta lliçó existeix des de les primeres versions de C#.
Versions més recents del llenguatge incorporen les anomenades switch expressions (una
forma més compacta d'escriure un switch que retorna un valor directament, sense
case/break) i el pattern matching avançat (comparar no només valors exactes, sinó
també tipus, rangs o estructures de dades completes). Com a avançament, així es veu una switch
expression equivalent a un dels exemples anteriors:
string categoria = "Narrativa";
string seccio = categoria switch
{
"Narrativa" => "Narrativa - Planta 1",
"Assaig" => "No ficcio - Planta 2",
"Poesia" => "Poesia - Planta 1",
_ => "Categoria no reconeguda"
};
Console.WriteLine(seccio);Per ara n'hi ha prou amb reconèixer aquesta sintaxi si la veus en codi aliè; no cal dominar-la
encara. El Mòdul 4 (Conceptes Avançats de C#) dedica una lliçó completa a Pattern Matching i
Característiques Modernes, on aprofundiràs en les switch expressions, els patrons de tipus,
de propietat i de rang. Per ara, domina bé el switch clàssic: és la base sobre la qual
s'entenen totes aquestes variants modernes.
- Aplicació completa: classificar un llibre per categoria
Construirem una petita utilitat de BiblioTechConsola que, donada la categoria d'un llibre, determina en quina planta se situa físicament i mostra un missatge descriptiu.
string[] categoriesLlibres = { "Narrativa", "Comic", "Assaig", "Infantil", "Manga", "Desconeguda" };
foreach (string categoria in categoriesLlibres)
{
string ubicacio;
switch (categoria)
{
case "Narrativa":
case "Ciencia Ficcio":
case "Fantasia":
ubicacio = "Planta 1 - Narrativa";
break;
case "Assaig":
case "Historia":
ubicacio = "Planta 2 - No ficcio";
break;
case "Infantil":
case "Juvenil":
ubicacio = "Planta baixa - Seccio familiar";
break;
case "Comic":
case "Manga":
ubicacio = "Planta 1 - Comic i manga";
break;
default:
ubicacio = "Sense ubicacio assignada - consulta amb el bibliotecari";
break;
}
Console.WriteLine($"{categoria} -> {ubicacio}");
}Sortida esperada:
Narrativa -> Planta 1 - Narrativa Comic -> Planta 1 - Comic i manga Assaig -> Planta 2 - No ficcio Infantil -> Planta baixa - Seccio familiar Manga -> Planta 1 - Comic i manga Desconeguda -> Sense ubicacio assignada - consulta amb el bibliotecari
Observa com el switch deixa el codi molt més ordenat que una llarga cadena de else if
comparant sempre la mateixa variable categoria.
Errors Comuns i Consells
- Oblidar el
break: a C# no compila uncaseamb codi que no acabi enbreak(o una altra instrucció de sortida comreturn). El compilador t'avisarà amb un error clar; no ho interpretis com un caprici del llenguatge, sinó com una protecció contra l'error de fall-through accidental tan comú en altres llenguatges. - Duplicar un valor de
case: dues etiquetescaseamb el mateix valor no compilen. Revisa que cada valor aparegui una sola vegada. - Oblidar el
default: tot i que no és obligatori, ometre'l pot deixar situacions sense cobrir. A BiblioTechConsola, undefaultben pensat ("categoria no reconeguda") evita comportaments silenciosos i inesperats. - Fer servir
switchper a rangs numèrics (pagines > 100 && pagines < 300): elswitchclàssic compara igualtat exacta, no rangs; per a això, fes servirif/else if/else. - Barrejar tipus de valors als
case: tots els valors delscasehan de ser compatibles amb el tipus de l'expressió delswitch(si compara unstring, tots elscasehan de ser cadenes literals).
Exercicis
-
Declara
int diaSetmanaamb un valor de l'1 al 7. Escriu unswitchque mostri per consola el nom del dia corresponent (1->"Dilluns", ...,7->"Diumenge"), i un missatge"Dia invalid"aldefault. -
Declara
string formatamb un d'aquests valors:"Tapa dura","Tapa tova","Digital","Audiollibre". Fent servircaseapilats, agrupa"Tapa dura"i"Tapa tova"sota el missatge"Format fisic", i agrupa"Digital"i"Audiollibre"sota el missatge"Format electronic". -
Donat l'array
string[] categories = { "Poesia", "Terror", "Narrativa" };, recorre l'array ambforeachi, per a cada categoria, fes servir unswitchper mostrar"Planta 1"si és"Narrativa"o"Poesia", i"Sense classificar"en qualsevol altre cas (inclòs"Terror", que no està contemplat explícitament).
Solucions
int diaSetmana = 3;
switch (diaSetmana)
{
case 1:
Console.WriteLine("Dilluns");
break;
case 2:
Console.WriteLine("Dimarts");
break;
case 3:
Console.WriteLine("Dimecres");
break;
case 4:
Console.WriteLine("Dijous");
break;
case 5:
Console.WriteLine("Divendres");
break;
case 6:
Console.WriteLine("Dissabte");
break;
case 7:
Console.WriteLine("Diumenge");
break;
default:
Console.WriteLine("Dia invalid");
break;
}
Amb diaSetmana = 3, el resultat mostrat és "Dimecres".
string format = "Digital";
switch (format)
{
case "Tapa dura":
case "Tapa tova":
Console.WriteLine("Format fisic");
break;
case "Digital":
case "Audiollibre":
Console.WriteLine("Format electronic");
break;
default:
Console.WriteLine("Format no reconegut");
break;
}
Amb format = "Digital", el resultat mostrat és "Format electronic".
string[] categories = { "Poesia", "Terror", "Narrativa" };
foreach (string categoria in categories)
{
switch (categoria)
{
case "Narrativa":
case "Poesia":
Console.WriteLine("Planta 1");
break;
default:
Console.WriteLine("Sense classificar");
break;
}
}
El resultat mostrat és: "Planta 1" (per a "Poesia"), "Sense classificar" (per a
"Terror", que cau al default en no estar contemplat) i "Planta 1" (per a
"Narrativa").
Conclusió
En aquesta lliçó has après a fer servir switch per comparar una mateixa variable contra una
llista de valors possibles de forma clara i ordenada, la importància del break a cada
case, com agrupar diversos valors sota una mateixa acció, i quan triar switch enfront de
if/else if/else. També has vist un breu tast de les switch expressions i el pattern
matching modern, que retomaràs en profunditat al Mòdul 4.
Fins ara, en tots els exemples d'aquest mòdul, el codi ha assumit que les dades arriben en el
format correcte. Però en un programa real, qualsevol operació —convertir text a número, accedir
a una posició d'un array, deixar un llibre que no existeix— pot fallar. A l'última lliçó
d'aquest mòdul, Gestió d'Excepcions, aprendràs a anticipar i gestionar aquests errors de
forma controlada amb try/catch/finally, perquè BiblioTechConsola no s'aturi bruscament
davant d'una dada inesperada.
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
