Condizioni e cicli per controllare il flusso di esecuzione del programma.
🖥️ In pratica con Windows Forms: Decisioni: if, else, switch e input sicuro e Ripetere e riutilizzare: cicli e metodi.
Cosa Imparerai in Questa Lezione
Le strutture di controllo sono il cuore della programmazione: permettono al tuo
programma di prendere decisioni (if-else, switch) e ripetere azioni
(for, while, foreach). Senza queste strutture, ogni programma
sarebbe una semplice sequenza lineare di istruzioni.
Strutture Condizionali
Le strutture condizionali permettono di eseguire blocchi di codice solo se determinate condizioni sono vere. Sono come i bivi sulla strada: in base alla condizione, il programma sceglie quale strada seguire.
Istruzione if-else
- If base - Una sola condizione
Esegue il codice solo se la condizione è vera.
If Base
int età = 18;
if (età >= 18)
{
Console.WriteLine("Sei maggiorenne");
}
// Se età < 18, non succede nulla
- If-else - Due alternative
Se la condizione è vera esegue il primo blocco, altrimenti il secondo.
If-Else
int età = 16;
if (età >= 18)
{
Console.WriteLine("Sei maggiorenne");
}
else
{
Console.WriteLine("Sei minorenne"); // Questo viene eseguito
}
- If-else if-else - Condizioni multiple
Verifica più condizioni in sequenza, esegue il primo blocco che è vero.
If-Else If-Else
int età = 15;
if (età < 13)
{
Console.WriteLine("Sei un bambino");
}
else if (età < 18)
{
Console.WriteLine("Sei un adolescente"); // Questo viene eseguito
}
else
{
Console.WriteLine("Sei un adulto");
}
💡 Regole Importanti per if-else
- La condizione deve sempre restituire un
bool(true/false) - Le parentesi graffe
{}sono opzionali per istruzioni singole, ma sempre consigliate - Solo il primo blocco che soddisfa la condizione viene eseguito
- L'
elseè opzionale e cattura tutti i casi non gestiti
Operatore Ternario (?:)
Una forma compatta per assegnare valori basati su una condizione semplice. Sostituisce un if-else quando serve solo assegnare un valore.
Sintassi Operatore Ternario
// Sintassi: condizione ? valoreSeVero : valoreSeFalso
int età = 20;
string messaggio = età >= 18 ? "Maggiorenne" : "Minorenne";
Console.WriteLine(messaggio); // "Maggiorenne"
// Equivalente a:
string messaggio;
if (età >= 18)
messaggio = "Maggiorenne";
else
messaggio = "Minorenne";
✅ Quando Usare il Ternario
Usa il ternario quando:
- Devi assegnare un valore basato su una condizione semplice
- La condizione e i valori sono brevi e chiari
Usa if-else quando:
- Devi eseguire più istruzioni
- La logica è complessa o annidata
Istruzione Switch
Lo switch è utile per confrontare una variabile con diversi valori possibili.
È più leggibile di molti if-else quando si confronta la stessa variabile con molti valori.
Switch Tradizionale
int giornoSettimana = 3;
switch (giornoSettimana)
{
case 1:
Console.WriteLine("Lunedì");
break;
case 2:
Console.WriteLine("Martedì");
break;
case 3:
Console.WriteLine("Mercoledì"); // Questo viene eseguito
break;
case 4:
Console.WriteLine("Giovedì");
break;
case 5:
Console.WriteLine("Venerdì");
break;
case 6:
Console.WriteLine("Sabato");
break;
case 7:
Console.WriteLine("Domenica");
break;
default:
Console.WriteLine("Giorno non valido");
break;
}
⚠️ IMPORTANTE: Il break è obbligatorio!
Ogni case deve terminare con break (o return).
Se manca, il programma non si compila (errore CS0163): a differenza di C, C++ e Java, in C# un case non può proseguire nel successivo (fall-through). Si può solo raggruppare più case vuoti sopra lo stesso blocco, come nell'esempio qui sotto.
Switch con Case Multipli
int giorno = 6;
switch (giorno)
{
case 1:
case 2:
case 3:
case 4:
case 5:
Console.WriteLine("Giorno lavorativo");
break;
case 6:
case 7:
Console.WriteLine("Fine settimana"); // Questo viene eseguito
break;
default:
Console.WriteLine("Giorno non valido");
break;
}
🆕 Switch Expression (C# 8.0+)
Dalla versione 8.0, C# introduce una sintassi più compatta e funzionale per gli switch, che restituisce direttamente un valore.
Switch Expression Moderno
int giornoSettimana = 3;
string nomeGiorno = giornoSettimana switch
{
1 => "Lunedì",
2 => "Martedì",
3 => "Mercoledì", // Questo viene restituito
4 => "Giovedì",
5 => "Venerdì",
6 => "Sabato",
7 => "Domenica",
_ => "Giorno non valido" // _ è il default
};
Console.WriteLine(nomeGiorno); // "Mercoledì"
Vantaggi: Più conciso, no break necessari, assegnazione diretta, più funzionale (restituisce un valore).
Cicli (Loops)
I cicli permettono di eseguire ripetutamente un blocco di codice finché una condizione è vera. Sono fondamentali per evitare di scrivere codice ripetitivo.
Ciclo for
Il ciclo for è utile quando conosci esattamente quante volte
vuoi ripetere un'azione. Ha tre parti: inizializzazione, condizione e incremento.
Sintassi for
// Sintassi: for (inizializzazione; condizione; incremento)
// {
// corpo del ciclo
// }
// Stampa i numeri da 1 a 10
for (int i = 1; i <= 10; i++)
{
Console.WriteLine(i);
}
// Spiegazione:
// 1. int i = 1 → inizializza i a 1 (solo la prima volta)
// 2. i <= 10 → controlla se continuare (ogni iterazione)
// 3. i++ → incrementa i (dopo ogni iterazione)
// 4. Console.WriteLine(i) → esegue il corpo
- For con Array
Perfetto per iterare su array usando gli indici.
For con Array
int[] numeri = { 10, 20, 30, 40, 50 };
for (int i = 0; i < numeri.Length; i++)
{
Console.WriteLine($"Elemento {i}: {numeri[i]}");
}
// Output:
// Elemento 0: 10
// Elemento 1: 20
// Elemento 2: 30
// ...
- For Inverso
Puoi iterare all'indietro cambiando l'incremento.
For al Contrario
// Countdown da 10 a 1
for (int i = 10; i >= 1; i--)
{
Console.WriteLine(i);
}
Console.WriteLine("Via!");
Ciclo while
Il ciclo while esegue il blocco finché la condizione è vera.
Utile quando non sai in anticipo quante iterazioni servono.
While Base
int contatore = 0;
while (contatore < 5)
{
Console.WriteLine($"Contatore: {contatore}");
contatore++; // ⚠️ NON dimenticare di incrementare!
}
// Output:
// Contatore: 0
// Contatore: 1
// Contatore: 2
// Contatore: 3
// Contatore: 4
⚠️ ATTENZIONE: Cicli Infiniti!
Se dimentichi di modificare la variabile di controllo, il ciclo non terminerà mai!
// ❌ ERRORE: Ciclo infinito!
int x = 0;
while (x < 5)
{
Console.WriteLine(x);
// Manca x++! Il ciclo non finirà mai!
}
// ✅ CORRETTO
int x = 0;
while (x < 5)
{
Console.WriteLine(x);
x++; // Incremento necessario
}
Ciclo do-while
Simile al while, ma garantisce almeno un'esecuzione del corpo.
La condizione viene controllata alla fine, non all'inizio.
Do-While - Input Validato
int numero;
do
{
Console.Write("Inserisci un numero maggiore di 10: ");
string input = Console.ReadLine();
int.TryParse(input, out numero);
} while (numero <= 10); // Ripete finché numero <= 10
Console.WriteLine($"Hai inserito: {numero}");
📊 while vs do-while
while
- Controlla PRIMA di eseguire
- Può eseguire 0 volte
- Usa quando: la condizione deve essere vera da subito
do-while
- Esegue PRIMA di controllare
- Esegue almeno 1 volta
- Usa quando: serve almeno un'esecuzione (es. menu, input)
Ciclo foreach
Il ciclo foreach itera su collezioni (array, liste) senza
gestire manualmente gli indici. È più semplice e sicuro del for quando non
serve l'indice.
Foreach con Array
string[] città = { "Roma", "Milano", "Napoli", "Torino" };
foreach (string città in città)
{
Console.WriteLine($"Città: {città}");
}
// Output:
// Città: Roma
// Città: Milano
// Città: Napoli
// Città: Torino
Foreach con List
List<int> numeri = new List<int> { 10, 20, 30, 40, 50 };
foreach (int numero in numeri)
{
Console.WriteLine($"Numero: {numero}");
}
🔄 for vs foreach - Quando Usarli
Usa for quando:
- Serve l'indice corrente
- Devi modificare gli elementi
- Iteri all'indietro
- Devi saltare elementi
Usa foreach quando:
- Serve solo leggere i valori
- Non serve l'indice
- Codice più pulito e leggibile
- Meno probabilità di errori
Istruzioni di Controllo del Flusso
Queste istruzioni permettono di modificare il normale flusso di esecuzione dei cicli e dei metodi.
- break - Esce dal Ciclo
Termina immediatamente il ciclo più interno e continua dopo di esso.
Esempio break
// Cerca il primo numero maggiore di 15
int[] numeri = { 5, 10, 18, 22, 8 };
for (int i = 0; i < numeri.Length; i++)
{
if (numeri[i] > 15)
{
Console.WriteLine($"Trovato: {numeri[i]}");
break; // Esce dal ciclo immediatamente
}
}
// Output: Trovato: 18
// Il ciclo si ferma, non controlla 22 e 8
- continue - Salta all'Iterazione Successiva
Salta il resto del codice nel ciclo e passa alla prossima iterazione.
Esempio continue
// Stampa solo i numeri dispari
for (int i = 1; i <= 10; i++)
{
if (i % 2 == 0)
{
continue; // Salta i numeri pari
}
Console.WriteLine(i);
}
// Output: 1, 3, 5, 7, 9
// I numeri pari vengono saltati
- return - Termina il Metodo
Esce dal metodo corrente e (opzionalmente) restituisce un valore.
Esempio return
// Metodo che somma due numeri
int Somma(int a, int b)
{
return a + b; // Termina il metodo e restituisce il risultato
}
// Metodo che cerca un elemento
bool ContieneValore(int[] array, int valore)
{
foreach (int elemento in array)
{
if (elemento == valore)
{
return true; // Esce immediatamente se trovato
}
}
return false; // Se arriva qui, non è stato trovato
}
📊 Confronto break, continue, return
| Istruzione | Cosa fa | Dove si usa |
|---|---|---|
break |
Esce dal ciclo/switch corrente | Cicli (for, while, foreach) e switch |
continue |
Salta alla prossima iterazione | Solo nei cicli |
return |
Esce dal metodo (opzionalmente con valore) | Qualsiasi metodo |
Esempio Completo: Sistema di Classificazione
Vediamo un programma completo che utilizza tutte le strutture di controllo apprese per creare un sistema interattivo.
Program.cs - Sistema Completo
using System;
class Program
{
static void Main()
{
Console.WriteLine("=== SISTEMA DI CLASSIFICAZIONE ETÀ ===\n");
// INPUT CON VALIDAZIONE (do-while)
int età;
do
{
Console.Write("Inserisci la tua età (0-120): ");
string input = Console.ReadLine();
if (!int.TryParse(input, out età))
{
Console.WriteLine("Input non valido! Inserisci un numero.");
età = -1; // Forza ripetizione
}
else if (età < 0 || età > 120)
{
Console.WriteLine("Età non valida! Deve essere tra 0 e 120.");
}
} while (età < 0 || età > 120);
// CLASSIFICAZIONE CON IF-ELSE IF
string categoria;
if (età < 3)
{
categoria = "Neonato";
}
else if (età < 13)
{
categoria = "Bambino";
}
else if (età < 18)
{
categoria = "Adolescente";
}
else if (età < 65)
{
categoria = "Adulto";
}
else
{
categoria = "Anziano";
}
Console.WriteLine($"\nCategoria: {categoria}");
// SWITCH PER GIORNO DELLA SETTIMANA
Console.Write("\nInserisci giorno (1-7) per info settimana: ");
if (int.TryParse(Console.ReadLine(), out int giorno))
{
// Switch expression moderno
string tipoGiorno = giorno switch
{
>= 1 and <= 5 => "Giorno lavorativo",
6 or 7 => "Fine settimana",
_ => "Giorno non valido"
};
Console.WriteLine($"Tipo: {tipoGiorno}");
}
// CICLO FOR - Tabellina
Console.Write("\nVuoi vedere una tabellina? (s/n): ");
if (Console.ReadLine()?.ToLower() == "s")
{
Console.Write("Quale tabellina (1-10)? ");
if (int.TryParse(Console.ReadLine(), out int numero))
{
Console.WriteLine($"\nTabellina del {numero}:");
for (int i = 1; i <= 10; i++)
{
Console.WriteLine($"{numero} x {i} = {numero * i}");
}
}
}
// CICLO WHILE - Conta alla rovescia
Console.Write("\nVuoi un countdown? (s/n): ");
if (Console.ReadLine()?.ToLower() == "s")
{
int contatore = 5;
while (contatore > 0)
{
Console.WriteLine(contatore);
System.Threading.Thread.Sleep(1000); // Pausa 1 secondo
contatore--;
}
Console.WriteLine("Via!");
}
// FOREACH - Lista nomi
string[] nomiCategorie = { "Neonato", "Bambino", "Adolescente", "Adulto", "Anziano" };
Console.WriteLine("\n=== Categorie Disponibili ===");
foreach (string nome in nomiCategorie)
{
Console.WriteLine($"- {nome}");
}
// BREAK E CONTINUE - Ricerca
Console.WriteLine("\n=== Ricerca Numeri Pari ===");
int[] numeri = { 1, 4, 7, 8, 10, 11, 14, 15 };
int contaPari = 0;
foreach (int num in numeri)
{
if (num % 2 != 0)
{
continue; // Salta i dispari
}
Console.WriteLine($"Trovato numero pari: {num}");
contaPari++;
if (contaPari >= 3)
{
Console.WriteLine("Raggiunti 3 numeri pari, stop.");
break; // Esce dopo 3 pari
}
}
Console.WriteLine($"\nTotale numeri pari trovati: {contaPari}");
Console.WriteLine("\n=== FINE PROGRAMMA ===");
}
}
💡 Analisi del Codice
do-while- Validazione input (almeno 1 esecuzione garantita)if-else if- Classificazione età in categorieswitch expression- Tipo giorno (sintassi moderna C# 9)for- Tabellina (numero fisso di iterazioni)while- Countdown (condizione valutata prima)foreach- Iterazione su array senza indicicontinue- Salta numeri disparibreak- Esce dopo 3 numeri pari trovati
Esercizi Pratici
Esercizio 1: Calcolatore di Media Voti
Crea un programma che:
- Chiede quanti voti inserire (validazione con do-while)
- Usa un ciclo for per inserire i voti
- Salta i voti non validi (continue)
- Calcola e mostra la media
- Determina il giudizio con if-else o switch expression
Mostra la soluzione
Soluzione Esercizio 1
using System;
class Program
{
static void Main()
{
Console.WriteLine("=== CALCOLATORE MEDIA VOTI ===\n");
// Input numero voti con validazione
int numeroVoti;
do
{
Console.Write("Quanti voti vuoi inserire (1-20)? ");
string input = Console.ReadLine();
if (!int.TryParse(input, out numeroVoti) || numeroVoti < 1 || numeroVoti > 20)
{
Console.WriteLine("Numero non valido!");
numeroVoti = 0;
}
} while (numeroVoti < 1 || numeroVoti > 20);
// Inserimento voti
double somma = 0;
int votiValidi = 0;
for (int i = 1; i <= numeroVoti; i++)
{
Console.Write($"Voto {i} (18-30): ");
if (!int.TryParse(Console.ReadLine(), out int voto))
{
Console.WriteLine("Input non valido, saltato.");
continue; // Salta questo voto
}
if (voto < 18 || voto > 30)
{
Console.WriteLine("Voto non valido (18-30), saltato.");
continue; // Salta voti fuori range
}
somma += voto;
votiValidi++;
}
// Calcolo media
if (votiValidi == 0)
{
Console.WriteLine("\nNessun voto valido inserito!");
return;
}
double media = somma / votiValidi;
Console.WriteLine($"\nMedia: {media:F2} ({votiValidi}/{numeroVoti} voti validi)");
// Giudizio con switch expression
string giudizio = media switch
{
>= 28 => "Eccellente",
>= 24 => "Buono",
>= 21 => "Discreto",
>= 18 => "Sufficiente",
_ => "Non classificato"
};
Console.WriteLine($"Giudizio: {giudizio}");
}
}
Esercizio 2: Gioco Indovina il Numero
Crea un gioco in cui:
- Il computer sceglie un numero casuale (1-100)
- L'utente ha massimo 7 tentativi (for o while)
- Dai suggerimenti "troppo alto" o "troppo basso"
- Esci con break se indovina
- Mostra messaggi di vittoria/sconfitta
Mostra la soluzione
Soluzione Esercizio 2
using System;
class Program
{
static void Main()
{
Console.WriteLine("=== INDOVINA IL NUMERO ===\n");
Console.WriteLine("Ho pensato un numero tra 1 e 100.");
Console.WriteLine("Hai 7 tentativi!\n");
Random random = new Random();
int numeroSegreto = random.Next(1, 101); // 1-100
int tentativiMax = 7;
bool indovinato = false;
for (int tentativo = 1; tentativo <= tentativiMax; tentativo++)
{
Console.Write($"Tentativo {tentativo}/{tentativiMax}: ");
if (!int.TryParse(Console.ReadLine(), out int numeroUtente))
{
Console.WriteLine("Input non valido!");
continue; // Non conta come tentativo
}
if (numeroUtente < 1 || numeroUtente > 100)
{
Console.WriteLine("Numero fuori range (1-100)!");
continue;
}
// Controllo
if (numeroUtente == numeroSegreto)
{
Console.WriteLine($"\n🎉 COMPLIMENTI! Hai indovinato in {tentativo} tentativi!");
indovinato = true;
break; // Esce dal ciclo
}
else if (numeroUtente < numeroSegreto)
{
Console.WriteLine("📈 Troppo basso! Prova con un numero più alto.");
}
else
{
Console.WriteLine("📉 Troppo alto! Prova con un numero più basso.");
}
// Suggerimento finale
if (tentativo == tentativiMax - 1)
{
Console.WriteLine("\n⚠️ ULTIMO TENTATIVO!");
}
}
if (!indovinato)
{
Console.WriteLine($"\n😞 GAME OVER! Il numero era: {numeroSegreto}");
}
}
}
🎯 Riepilogo Lezione
Condizioni:
- if-else - Decisioni semplici
- else if - Condizioni multiple
- Operatore ternario - Assegnazioni veloci
- switch - Confronti multipli
- switch expression - Sintassi moderna
Cicli:
- for - Iterazioni fisse
- while - Condizione prima
- do-while - Almeno 1 esecuzione
- foreach - Collezioni semplici
- break, continue, return - Controllo flusso