Far ripetere le istruzioni al programma con for, while e do-while, ricordare valori tra un clic e l'altro, e scrivere metodi propri con parametri e return per non copiare il codice.
Negli esercizi precedenti ogni clic eseguiva le istruzioni una volta sola. Ma come si stampa la tabellina del 7 senza scrivere dieci righe quasi uguali? E se lo stesso calcolo serve in tre bottoni diversi, bisogna copiarlo tre volte? No: per ripetere si usano i cicli, per riutilizzare si usano i metodi.
In questa lezione impari a:
- ripetere istruzioni con for, while e do-while;
- usare contatori e accumulatori (somme, conteggi, massimo);
- far ricordare al form un valore tra un clic e l'altro;
- scrivere metodi tuoi, con parametri e return.
Per mostrare tanti risultati useremo una TextBox su più righe: aggiungi una TextBox, chiamala
txtOutpute nelle Proprietà impostaMultiline= True,ScrollBars= Vertical eReadOnly= True. Poi allargala con i quadratini bianchi. Nella prossima lezione vedrai la ListBox, fatta apposta per gli elenchi.
Il ciclo for: ripetere un numero preciso di volte
Il for si usa quando sai quante volte ripetere. Ha tre parti, separate dal punto e virgola:
for (int i = 1; i <= 10; i++)
{
// istruzioni ripetute
}
| Parte | Esempio | Quando viene eseguita |
|---|---|---|
| inizio | int i = 1 | una volta sola, prima di cominciare: crea il contatore |
| condizione | i <= 10 | prima di ogni giro: se è vera si entra, se è falsa il ciclo finisce |
| passo | i++ | alla fine di ogni giro: aumenta il contatore di 1 |
Esempio: la tabellina. Sul form ci sono txtNumero, btnTabellina e la TextBox txtOutput.
private void btnTabellina_Click(object sender, EventArgs e)
{
int n;
if (!int.TryParse(txtNumero.Text, out n))
{
MessageBox.Show("Scrivi un numero intero.");
return;
}
txtOutput.Clear(); // svuota l'output precedente
for (int i = 1; i <= 10; i++)
{
txtOutput.AppendText(n + " x " + i + " = " + (n * i) + Environment.NewLine);
}
}
AppendText aggiunge il testo in fondo alla TextBox; Environment.NewLine va a capo.
Prova: guarda il for giro per giro
Cambia i tre pezzi del for e premi Esegui: la tabella mostra, per ogni giro, quanto vale i, se la condizione è vera e cosa viene scritto. Prova anche a contare all'indietro (inizio 10, condizione i >= 1, passo i--) o di due in due (i += 2).
for (int i = ; i ; ) txtOutput.AppendText("Giro " + i);Contatori e accumulatori
Dentro un ciclo si usano spesso due tipi di variabili, sempre create prima del ciclo:
- il contatore conta quante volte succede qualcosa:
conta++; - l'accumulatore raccoglie un totale:
somma = somma + i(oppuresomma += i).
// Somma dei numeri da 1 a N, e quanti di questi sono pari
int somma = 0; // accumulatore: parte da 0
int pari = 0; // contatore: parte da 0
for (int i = 1; i <= n; i++)
{
somma += i;
if (i % 2 == 0)
{
pari++;
}
}
lblRisultato.Text = "Somma: " + somma + " — numeri pari: " + pari;
Attenzione: se scrivi
int somma = 0;dentro le graffe delfor, la somma riparte da zero a ogni giro e, finito il ciclo, non esiste più. Le variabili che devono "sopravvivere" al ciclo vanno create prima.
Il ciclo while: ripetere finché serve
Il while ("finché") si usa quando non sai in anticipo quante volte ripetere: continua finché la condizione resta vera.
// Quanti anni servono per raddoppiare un capitale al 5% annuo?
double capitale = 1000;
int anni = 0;
while (capitale < 2000)
{
capitale = capitale * 1.05;
anni++;
}
lblRisultato.Text = "Servono " + anni + " anni"; // 15 anni
Il do ... while è uguale, ma controlla la condizione alla fine: il blocco viene eseguito almeno una volta.
int n = 1;
do
{
txtOutput.AppendText(n + " ");
n = n * 2;
} while (n <= 100); // scrive 1 2 4 8 16 32 64 — notare il ; finale
Attenzione al ciclo infinito: se dentro il
whilenon cambia niente che possa rendere falsa la condizione, il ciclo non finisce mai e il form si blocca ("Non risponde"). In Visual Studio si ferma conMaiusc+F5. Controlla sempre che la variabile della condizione venga modificata a ogni giro.
Quale ciclo usare?
| Situazione | Ciclo |
|---|---|
| So quante volte ripetere (da 1 a 10, per ogni carattere di una parola…) | for |
| Ripeto finché succede qualcosa (raddoppio, numero trovato…) | while |
| Come while, ma il blocco va eseguito almeno una volta | do ... while |
| Scorro tutti gli elementi di una lista | foreach (prossima lezione) |
break esce subito dal ciclo; continue salta il resto del giro e passa al successivo.
// Il primo divisore di n maggiore di 1
for (int d = 2; d <= n; d++)
{
if (n % d == 0)
{
lblRisultato.Text = "Il primo divisore è " + d;
break; // trovato: inutile continuare
}
}
Ricordare un valore tra un clic e l'altro
Le variabili create dentro un metodo _Click spariscono alla fine del metodo: al clic successivo ripartono da capo. Se il form deve ricordare qualcosa (quanti clic, un numero segreto, un totale), la variabile va dichiarata fuori dai metodi, dentro la classe del form. Si chiama campo (o variabile del form).
public partial class Form1 : Form
{
int contaClic = 0; // campo: esiste finché il form è aperto
public Form1()
{
InitializeComponent();
}
private void btnClic_Click(object sender, EventArgs e)
{
contaClic++; // non riparte da 0: si ricorda il valore
lblConta.Text = "Hai cliccato " + contaClic + " volte";
}
private void btnAzzera_Click(object sender, EventArgs e)
{
contaClic = 0; // tutti i metodi del form lo vedono
lblConta.Text = "Contatore azzerato";
}
}
| Dove la dichiaro | Chi la vede | Quanto dura |
|---|---|---|
dentro le graffe di un for o di un if | solo quel blocco | finché il blocco non finisce |
dentro un metodo (es. btnClic_Click) | solo quel metodo | finché il metodo non finisce |
| fuori dai metodi, nella classe del form (campo) | tutti i metodi del form | finché il form è aperto |
I metodi: scrivere il codice una volta sola
Un metodo è un blocco di codice con un nome, che puoi chiamare quando ti serve. Ne usi già tanti: MessageBox.Show(...), int.TryParse(...), txtOutput.Clear(). Ora impari a scriverne di tuoi.
Si scrivono dentro la classe del form, fuori dagli altri metodi (per esempio sotto l'ultimo _Click).
private double CelsiusInFahrenheit(double celsius)
{
double fahrenheit = celsius * 9 / 5 + 32;
return fahrenheit;
}
| Pezzo | Significato |
|---|---|
private | il metodo si usa solo dentro questo form |
double | il tipo del risultato che il metodo restituisce; void se non restituisce niente |
CelsiusInFahrenheit | il nome: un verbo o una descrizione chiara, con le iniziali maiuscole |
(double celsius) | il parametro: il dato che il metodo riceve da chi lo chiama |
return fahrenheit; | restituisce il risultato e termina il metodo |
Ora lo stesso calcolo si usa dove serve, con una riga:
private void btnConverti_Click(object sender, EventArgs e)
{
double c;
if (double.TryParse(txtCelsius.Text, out c))
{
lblRisultato.Text = CelsiusInFahrenheit(c) + " °F";
}
}
private void btnTabella_Click(object sender, EventArgs e)
{
txtOutput.Clear();
for (int c = -10; c <= 40; c += 10)
{
txtOutput.AppendText(c + " °C = " + CelsiusInFahrenheit(c) + " °F" + Environment.NewLine);
}
}
Se un giorno la formula va corretta, la cambi in un solo punto e tutti e due i bottoni si aggiornano.
Prova: segui la chiamata di un metodo
Premi Passo per eseguire il codice una riga alla volta. Guarda il riquadro delle variabili: quando il programma entra nel metodo, il parametro riceve il valore; quando incontra return, il risultato torna al punto della chiamata.
Tipi di metodi
| Tipo | Esempio | Si chiama così |
|---|---|---|
| senza parametri, senza risultato | private void PulisciForm() | PulisciForm(); |
| con parametri, senza risultato | private void Avvisa(string testo) | Avvisa("Campo vuoto"); |
| con parametri e risultato | private int Somma(int a, int b) | int s = Somma(3, 4); |
| che risponde sì o no | private bool EPari(int n) | if (EPari(x)) { ... } |
// Un metodo void: rimette il form come all'inizio
private void PulisciForm()
{
txtNumero.Clear();
txtOutput.Clear();
lblRisultato.Text = "";
txtNumero.Focus();
}
// Un metodo bool: ciclo + return dentro un metodo
private bool EPrimo(int n)
{
if (n < 2)
{
return false;
}
for (int d = 2; d * d <= n; d++)
{
if (n % d == 0)
{
return false; // trovato un divisore: non è primo, esce subito
}
}
return true; // nessun divisore trovato
}
Attenzione: un metodo che non è
voiddeve arrivare sempre a unreturn, qualunque strada prenda. Se manca, Visual Studio segnala l'errore "non tutti i percorsi del codice restituiscono un valore".
Quando creare un metodo? Quando ti accorgi di copiare e incollare lo stesso pezzo di codice, oppure quando un _Click diventa così lungo che non si capisce più cosa fa. Un metodo con un buon nome (CalcolaMedia, EPrimo, PulisciForm) rende il codice leggibile come una frase.
Gli errori più comuni
| Errore | Cosa succede | Correzione |
|---|---|---|
for (int i = 1; i <= 10; i++); | il ; chiude il for: il blocco sotto viene eseguito una volta sola | niente ; dopo la parentesi |
i < 10 invece di i <= 10 | un giro in meno (manca il 10) | controlla primo e ultimo valore |
| accumulatore dentro il ciclo | riparte da 0 a ogni giro | dichiaralo prima del ciclo |
| while senza modificare la variabile | ciclo infinito, il form non risponde | cambia la variabile a ogni giro |
contatore dentro il _Click | non ricorda i clic precedenti | dichiaralo come campo del form |
| metodo scritto dentro un altro metodo | errori strani di parentesi | ogni metodo va fuori dagli altri, dentro la classe |
int r = Saluta(); con Saluta void | errore: un void non restituisce niente | usa return e un tipo di ritorno |
Esercizi
Esercizio 1 – Somma e media. Una TextBox txtN e un bottone. Il programma calcola la somma dei numeri da 1 a N e la loro media, e scrive in txtOutput tutti i numeri dispari da 1 a N.
Mostra la soluzione
private void btnCalcola_Click(object sender, EventArgs e)
{
int n;
if (!int.TryParse(txtN.Text, out n) || n < 1)
{
MessageBox.Show("Scrivi un numero intero maggiore di 0.");
return;
}
txtOutput.Clear();
int somma = 0;
for (int i = 1; i <= n; i++)
{
somma += i;
if (i % 2 == 1)
{
txtOutput.AppendText(i + " ");
}
}
double media = (double)somma / n; // (double) evita la divisione tra interi
lblRisultato.Text = "Somma: " + somma + " — media: " + media;
}
Senza (double), somma / n sarebbe una divisione tra interi e perderebbe i decimali.
Esercizio 2 – Indovina il numero. All'apertura del form il computer sceglie un numero segreto da 1 a 100. L'utente prova con una TextBox e un bottone: il programma risponde "più alto", "più basso" o "Indovinato in N tentativi!". Un secondo bottone ricomincia la partita.
Suggerimento: il numero segreto e i tentativi devono essere campi del form. Un numero casuale si ottiene con Random: new Random().Next(1, 101) dà un numero da 1 a 100.
Mostra la soluzione
public partial class Form1 : Form
{
Random caso = new Random();
int segreto;
int tentativi;
public Form1()
{
InitializeComponent();
NuovaPartita();
}
private void NuovaPartita()
{
segreto = caso.Next(1, 101);
tentativi = 0;
lblEsito.Text = "Ho pensato un numero da 1 a 100";
txtTentativo.Clear();
txtTentativo.Focus();
}
private void btnProva_Click(object sender, EventArgs e)
{
int numero;
if (!int.TryParse(txtTentativo.Text, out numero))
{
MessageBox.Show("Scrivi un numero.");
return;
}
tentativi++;
if (numero < segreto)
{
lblEsito.Text = numero + ": più alto!";
}
else if (numero > segreto)
{
lblEsito.Text = numero + ": più basso!";
}
else
{
lblEsito.Text = "Indovinato in " + tentativi + " tentativi!";
}
txtTentativo.SelectAll();
txtTentativo.Focus();
}
private void btnNuova_Click(object sender, EventArgs e)
{
NuovaPartita();
}
}
NuovaPartita() è un metodo usato in due punti: nel costruttore (all'apertura) e nel bottone "Nuova partita".
Esercizio 3 – Numeri primi. Usa il metodo EPrimo della lezione: l'utente scrive N e il programma elenca in txtOutput tutti i numeri primi fino a N, poi scrive quanti sono.
Mostra la soluzione
private void btnPrimi_Click(object sender, EventArgs e)
{
int n;
if (!int.TryParse(txtN.Text, out n) || n < 2)
{
MessageBox.Show("Scrivi un numero intero da 2 in su.");
return;
}
txtOutput.Clear();
int quanti = 0;
for (int i = 2; i <= n; i++)
{
if (EPrimo(i))
{
txtOutput.AppendText(i + " ");
quanti++;
}
}
lblRisultato.Text = "Numeri primi trovati: " + quanti;
}
Il ciclo del bottone chiama EPrimo, che a sua volta contiene un altro ciclo: il codice resta corto e leggibile.
Esercizio 4 – Il salvadanaio. Il form ha una TextBox per l'importo e due bottoni, Versa e Preleva. Il saldo (campo del form) parte da 0 e non può andare sotto zero. Scrivi un metodo LeggiImporto() che restituisce l'importo scritto, oppure -1 se non è un numero positivo, e un metodo AggiornaSaldo() che scrive il saldo nella Label. Usali tutti e due in entrambi i bottoni.
Mostra la soluzione
public partial class Form1 : Form
{
double saldo = 0;
public Form1()
{
InitializeComponent();
AggiornaSaldo();
}
private double LeggiImporto()
{
double importo;
if (double.TryParse(txtImporto.Text, out importo) && importo > 0)
{
return importo;
}
MessageBox.Show("Scrivi un importo positivo (es. 12,50).");
return -1;
}
private void AggiornaSaldo()
{
lblSaldo.Text = "Saldo: " + saldo.ToString("0.00") + " €";
txtImporto.Clear();
}
private void btnVersa_Click(object sender, EventArgs e)
{
double importo = LeggiImporto();
if (importo == -1) return;
saldo += importo;
AggiornaSaldo();
}
private void btnPreleva_Click(object sender, EventArgs e)
{
double importo = LeggiImporto();
if (importo == -1) return;
if (importo > saldo)
{
MessageBox.Show("Saldo insufficiente.");
return;
}
saldo -= importo;
AggiornaSaldo();
}
}
saldo.ToString("0.00") scrive sempre due cifre decimali.
Riepilogo
| Strumento | A cosa serve |
|---|---|
for (inizio; condizione; passo) | ripetere un numero preciso di volte |
while (condizione) / do ... while | ripetere finché la condizione è vera (do-while almeno una volta) |
break / continue | uscire dal ciclo / saltare al giro successivo |
| contatore e accumulatore | contare e sommare durante il ciclo; si dichiarano prima |
| campo del form | variabile che il form ricorda tra un clic e l'altro |
metodo con void | esegue delle istruzioni, non restituisce niente |
metodo con tipo e return | calcola e restituisce un risultato |
| parametri | i dati che il metodo riceve da chi lo chiama |
📚 Teoria collegata (percorso C# – il linguaggio, esempi in console): Strutture di controllo e Funzioni e metodi.