Da semplici operazioni a validazioni avanzate: impara facendo.
Il Tuo Percorso Finora
Hai completato un percorso incredibile! Vediamo cosa hai giΓ imparato e cosa farai in questa lezione:
β Competenze GiΓ Acquisite
- β Visual Studio e primi passi: progetto Windows Forms, Button, evento Click, MessageBox
- β Variabili e operatori: int, double, string, bool, calcoli e conversioni
- β Decisioni: if, else if, else, switch, TryParse e try/catch
- β TextBox e Label: leggere l'input dell'utente e mostrare i risultati
π― Focus di Questa Lezione
Ora Γ¨ tempo di mettere insieme tutto questo con esercizi pratici progressivi che combinano:
- π’ Operazioni matematiche con validazione input
- β Strutture di controllo (if/else, switch) applicate a interfacce grafiche
- π¨ Feedback visivo dinamico (colori, messaggi, abilitazione controlli)
- π Conversioni di tipo sicure (TryParse vs Convert)
- π Validazione complessa con piΓΉ condizioni
π‘ PerchΓ© Questa Lezione Γ¨ Importante
Gli esercizi di questa lezione ti permettono di praticare intensivamente i concetti fondamentali della programmazione (operatori, condizioni, conversioni) attraverso interfacce grafiche. Non stai solo scrivendo codice astratto: stai creando applicazioni reali che gli utenti possono usare!
Ogni esercizio introduce nuovi concetti teorici nel contesto pratico, preparandoti gradualmente per le lezioni teoriche approfondite che seguiranno.
π Concetti Fondamentali Praticati
TextBox
Controllo per l'inserimento di testo e numeri
Label
Controllo per visualizzare testo e risultati
Button
Controllo che genera evento Click per azioni
Event Handler
Metodo eseguito quando si verifica un evento
Esercizio 1: Calcolatrice - Somma di Due Numeri
Obiettivo
Creare la tua prima calcolatrice con interfaccia grafica! L'applicazione permette di inserire due numeri, calcolare la somma e visualizzare il risultato. Include validazione per evitare errori quando l'utente inserisce testo al posto di numeri.
π― Cosa Imparerai:
- β Raccogliere input numerici da TextBox
- β
Convertire stringhe in numeri con
Convert.ToDouble() - β Eseguire operazioni matematiche (somma)
- β
Gestire errori con
try-catch - β
Validare input con
string.IsNullOrEmpty() - β Abilitare/disabilitare controlli dinamicamente
- Progettazione dell'Interfaccia Grafica
Crea un nuovo Windows Forms Project:
- File β Nuovo β Progetto
- Seleziona "Applicazione Windows Forms (.NET Framework)"
- Nome:
CalcolatoriceSomma - Click su "Crea"
π Controlli da Aggiungere al Form:
| Tipo Controllo | Name (Nome) | ProprietΓ Text | Note |
|---|---|---|---|
| Label | lblNumero1 | "Primo Numero:" | Etichetta descrittiva |
| TextBox | txtNumero1 |
vuoto | Input primo numero |
| Label | lblNumero2 | "Secondo Numero:" | Etichetta descrittiva |
| TextBox | txtNumero2 |
vuoto | Input secondo numero |
| Button | btnCalcola |
"Calcola Somma" | Inizialmente disabilitato (Enabled = false) |
| Label | lblRisultato |
vuoto | Mostra risultato (Font: 14pt, Bold) |
πΈ Come Dovrebbe Apparire l'Interfaccia:
Disponi i controlli in verticale: Label "Primo Numero:", sotto la TextBox txtNumero1, poi Label "Secondo Numero:", sotto la TextBox txtNumero2, poi il Button btnCalcola, e in fondo la Label lblRisultato per mostrare il risultato.
- Gestione dell'Evento Click del Pulsante
Quando l'utente clicca sul pulsante "Calcola Somma", dobbiamo:
- Verificare che entrambi i campi siano compilati
- Convertire i testi in numeri
- Calcolare la somma
- Mostrare il risultato
- Gestire eventuali errori
Form1.cs - Evento Click
using System;
using System.Windows.Forms;
namespace CalcolatriceSomma
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// EVENTO: Click del pulsante "Calcola Somma"
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
private void btnCalcola_Click(object sender, EventArgs e)
{
// βββββββββββββββββββββββββββββββββββββββββββββββββ
// STEP 1: Validazione - Controllo campi vuoti
// βββββββββββββββββββββββββββββββββββββββββββββββββ
// string.IsNullOrEmpty() verifica se la stringa Γ¨ null o vuota ("")
if (string.IsNullOrEmpty(txtNumero1.Text) ||
string.IsNullOrEmpty(txtNumero2.Text))
{
lblRisultato.Text = "β οΈ Inserisci entrambi i numeri!";
lblRisultato.ForeColor = System.Drawing.Color.Red;
return; // Esce dal metodo senza eseguire altro codice
}
// βββββββββββββββββββββββββββββββββββββββββββββββββ
// STEP 2: Conversione e Calcolo (con gestione errori)
// βββββββββββββββββββββββββββββββββββββββββββββββββ
try
{
// Converti le stringhe in numeri decimali (double)
// Convert.ToDouble() puΓ² generare eccezione se il testo non Γ¨ un numero
double numero1 = Convert.ToDouble(txtNumero1.Text);
double numero2 = Convert.ToDouble(txtNumero2.Text);
// Calcola la somma
double somma = numero1 + numero2;
// βββββββββββββββββββββββββββββββββββββββββββββ
// STEP 3: Visualizzazione Risultato
// βββββββββββββββββββββββββββββββββββββββββββββ
// ToString() converte il numero in stringa per visualizzarlo
lblRisultato.Text = "Risultato: " + somma.ToString();
lblRisultato.ForeColor = System.Drawing.Color.Green;
}
catch (FormatException)
{
// Eccezione catturata se l'utente inserisce testo non numerico
lblRisultato.Text = "β Inserisci valori numerici validi!";
lblRisultato.ForeColor = System.Drawing.Color.Red;
}
catch (Exception ex)
{
// Cattura qualsiasi altra eccezione non prevista
lblRisultato.Text = "β Errore: " + ex.Message;
lblRisultato.ForeColor = System.Drawing.Color.Red;
}
}
}
}
π Analisi Dettagliata del Codice:
1οΈβ£ Validazione Input:
if (string.IsNullOrEmpty(txtNumero1.Text) ||
string.IsNullOrEmpty(txtNumero2.Text))
{
// Almeno uno dei due campi Γ¨ vuoto
lblRisultato.Text = "β οΈ Inserisci entrambi i numeri!";
return; // IMPORTANTE: interrompe l'esecuzione del metodo
}
L'operatore || (OR logico) restituisce true se
almeno una delle condizioni Γ¨ vera. Se uno dei campi Γ¨ vuoto,
mostra errore e return esce dal metodo.
2οΈβ£ Try-Catch per Gestione Errori:
try
{
// Codice che potrebbe generare errori
double numero1 = Convert.ToDouble(txtNumero1.Text);
}
catch (FormatException)
{
// Gestisce l'errore se Convert fallisce
lblRisultato.Text = "β Inserisci valori numerici!";
}
try-catch permette di "catturare" errori senza far crashare il programma.
Se Convert.ToDouble("abc") fallisce, invece di chiudere l'app,
il controllo passa al blocco catch.
3οΈβ£ Conversione con ToString():
double somma = 15.5;
lblRisultato.Text = "Risultato: " + somma.ToString();
// Output: "Risultato: 15.5"
.Text richiede una stringa. ToString() converte
il numero in stringa per poterlo concatenare con testo.
- Validazione Dinamica con TextChanged
Miglioriamo l'app abilitando il pulsante "Calcola" solo quando entrambi i campi contengono numeri validi. Questo offre feedback immediato all'utente!
Form1.cs - Eventi TextChanged
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// EVENTI: TextChanged per validazione dinamica
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
private void txtNumero1_TextChanged(object sender, EventArgs e)
{
// Abilita il pulsante solo se entrambi i campi sono validi
btnCalcola.Enabled = ValidaInput();
}
private void txtNumero2_TextChanged(object sender, EventArgs e)
{
// Stesso controllo per il secondo campo
btnCalcola.Enabled = ValidaInput();
}
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// METODO HELPER: Valida che entrambi i campi siano numeri
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
private bool ValidaInput()
{
try
{
// Prova a convertire il primo numero
if (!string.IsNullOrEmpty(txtNumero1.Text))
Convert.ToDouble(txtNumero1.Text);
// Prova a convertire il secondo numero
if (!string.IsNullOrEmpty(txtNumero2.Text))
Convert.ToDouble(txtNumero2.Text);
// Se arriviamo qui, entrambi sono numeri validi
return true;
}
catch
{
// Se Convert fallisce, ritorna false
return false;
}
}
β‘ Come Collegare gli Eventi TextChanged:
- Seleziona
txtNumero1nel Designer - Premi
F4per aprire le ProprietΓ - Clicca sull'icona del fulmine β‘ (Eventi)
- Trova TextChanged e fai doppio click
- Visual Studio crea automaticamente il metodo
txtNumero1_TextChanged - Ripeti per
txtNumero2
π¬ Flusso di Esecuzione:
- Utente apre l'app β
btnCalcola.Enabled = false(disabilitato) - Utente scrive "12" in txtNumero1 β Evento
txtNumero1_TextChanged - Chiama
ValidaInput()β txtNumero2 Γ¨ vuoto β return false btnCalcola.Enabled = falseβ Pulsante ancora disabilitato- Utente scrive "8" in txtNumero2 β Evento
txtNumero2_TextChanged - Chiama
ValidaInput()β Entrambi sono numeri validi β return true btnCalcola.Enabled = trueβ β Pulsante si abilita!- Utente clicca "Calcola Somma" β Evento
btnCalcola_Click - Calcola 12 + 8 = 20 β Mostra "Risultato: 20" (verde)
Metodi e Concetti - Esercizio 1
string.IsNullOrEmpty(string)
Metodo statico che verifica se una stringa Γ¨ null (non esiste) o vuota (""). Essenziale per validare campi obbligatori.
// Sintassi:
bool risultato = string.IsNullOrEmpty(testo);
// Esempi:
string.IsNullOrEmpty("") // true (stringa vuota)
string.IsNullOrEmpty("Mario") // false (ha contenuto)
string.IsNullOrEmpty(null) // true (non esiste)
// Uso pratico:
if (string.IsNullOrEmpty(txtNome.Text))
{
MessageBox.Show("Il campo Γ¨ obbligatorio!");
}
π‘ PerchΓ© Preferibile a txt.Text == "":
txt.Text == ""β Crash se txt.Text Γ¨ nullstring.IsNullOrEmpty(txt.Text)β Gestisce sia null che ""
Convert.ToDouble(string)
Converte una stringa in numero decimale (double). Genera eccezione FormatException se la stringa non Γ¨ numerica.
// Sintassi:
double numero = Convert.ToDouble(stringa);
// Esempi:
Convert.ToDouble("123.45") // 123.45
Convert.ToDouble("100") // 100.0
Convert.ToDouble("abc") // β FormatException (errore!)
Convert.ToDouble("") // β FormatException (errore!)
// Uso con try-catch:
try
{
double num = Convert.ToDouble(txtInput.Text);
// Usa "num" sapendo che Γ¨ valido
}
catch (FormatException)
{
MessageBox.Show("Inserisci un numero valido!");
}
β οΈ Quando Usare Convert vs TryParse:
Convert.ToDouble()β Usa con try-catch (solleva eccezioni)double.TryParse()β Usa senza try-catch (ritorna true/false)- TryParse Γ¨ generalmente preferibile per input utente
.ToString()
Converte qualsiasi valore nel suo equivalente rappresentazione stringa. Tutti i tipi ereditano questo metodo.
// Sintassi:
string testo = valore.ToString();
// Esempi con numeri:
int numero = 42;
numero.ToString() // "42"
double decimale = 3.14;
decimale.ToString() // "3.14"
decimale.ToString("F2") // "3.14" (2 decimali)
decimale.ToString("F0") // "3" (nessun decimale)
// Concatenazione con stringhe:
int eta = 25;
string messaggio = "Hai " + eta.ToString() + " anni";
// oppure (piΓΉ moderno):
string messaggio2 = $"Hai {eta} anni"; // string interpolation
try-catch (Gestione Eccezioni)
Costrutto per gestire errori (eccezioni) a runtime senza far crashare il programma.
// Struttura base:
try
{
// Codice che potrebbe generare errori
double num = Convert.ToDouble(txtInput.Text);
}
catch (FormatException ex)
{
// Gestisce errori di formato (testo non numerico)
MessageBox.Show("Inserisci un numero valido!");
}
catch (Exception ex)
{
// Cattura tutte le altre eccezioni
MessageBox.Show("Errore: " + ex.Message);
}
// Best Practice: gestisci eccezioni specifiche prima
try
{
// ...
}
catch (FormatException) // Specifica
{
// Errore formato
}
catch (OverflowException) // Specifica
{
// Numero troppo grande
}
catch (Exception ex) // Generica (ultima)
{
// Altri errori
}
Control.Enabled (proprietΓ )
ProprietΓ booleana che indica se un controllo Γ¨ abilitato (true) o disabilitato (false). Controlli disabilitati appaiono in grigio e non rispondono a eventi.
// Abilitare/disabilitare:
btnCalcola.Enabled = true; // Abilita (cliccabile)
btnCalcola.Enabled = false; // Disabilita (grigio, non cliccabile)
// Uso dinamico:
btnCalcola.Enabled = ValidaInput(); // Abilita se ValidaInput() ritorna true
// Controlli multipli:
bool tuttiValidi = VerificaCampi();
btnSalva.Enabled = tuttiValidi;
btnInvia.Enabled = tuttiValidi;
Operatore || (OR Logico)
Restituisce true se almeno una delle condizioni Γ¨ vera.
// Tabella di veritΓ :
true || true // true
true || false // true
false || true // true
false || false // false
// Uso pratico - almeno uno deve essere vero:
if (string.IsNullOrEmpty(txtNome.Text) ||
string.IsNullOrEmpty(txtCognome.Text))
{
// Se Nome Γ¨ vuoto OR Cognome Γ¨ vuoto (o entrambi)
MessageBox.Show("Compila tutti i campi!");
}
// Differenza con && (AND):
// && β TUTTI devono essere veri
// || β ALMENO UNO deve essere vero
Esercizio 2: Verifica Numero Pari o Dispari
Obiettivo
Creare un'applicazione che determina se un numero inserito dall'utente Γ¨ pari o dispari.
Introduce l'operatore modulo (%) e l'uso di strutture condizionali (if-else)
con feedback visivo colorato.
π― Nuovi Concetti:
- β
Operatore modulo (
%) per calcolare il resto della divisione - β
if-elseper eseguire codice condizionalmente - β
Convert.ToInt32()per numeri interi - β
Cambiare colore del testo con
ForeColor - β
Evento
KeyPressper filtrare input in tempo reale
π Teoria: Numeri Pari e Dispari
Un numero Γ¨ pari se Γ¨ divisibile per 2 senza resto (resto = 0). Un numero Γ¨ dispari se diviso per 2 lascia resto 1.
// Esempi:
10 diviso 2 = 5 resto 0 β PARI
7 diviso 2 = 3 resto 1 β DISPARI
-4 diviso 2 = -2 resto 0 β PARI
0 diviso 2 = 0 resto 0 β PARI
// Operatore modulo (%):
10 % 2 = 0 // resto della divisione 10/2
7 % 2 = 1 // resto della divisione 7/2
// Regola generale:
if (numero % 2 == 0)
// PARI
else
// DISPARI
- Progettazione dell'Interfaccia
| Tipo | Name | Text | Note |
|---|---|---|---|
| Label | lblTitolo | "Inserisci un Numero:" | - |
| TextBox | txtNumero |
vuoto | Input numero intero |
| Button | btnVerifica |
"Verifica" | - |
| Label | lblRisultato |
vuoto | Font: 14pt, Bold |
- Codice Completo con Spiegazione
Form1.cs - Verifica Pari/Dispari
using System;
using System.Drawing;
using System.Windows.Forms;
namespace VerificaPariDispari
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// EVENTO: Click del pulsante "Verifica"
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
private void btnVerifica_Click(object sender, EventArgs e)
{
// βββββββββββββββββββββββββββββββββββββββββββββββββ
// STEP 1: Validazione campo vuoto
// βββββββββββββββββββββββββββββββββββββββββββββββββ
if (string.IsNullOrEmpty(txtNumero.Text))
{
lblRisultato.Text = "β οΈ Inserisci un numero!";
lblRisultato.ForeColor = Color.Gray;
return;
}
try
{
// βββββββββββββββββββββββββββββββββββββββββββββ
// STEP 2: Conversione in intero
// βββββββββββββββββββββββββββββββββββββββββββββ
// Convert.ToInt32() converte in numero intero (int)
// a differenza di ToDouble(), ToInt32() non accetta decimali
int numero = Convert.ToInt32(txtNumero.Text);
// βββββββββββββββββββββββββββββββββββββββββββββ
// STEP 3: Verifica con operatore modulo (%)
// βββββββββββββββββββββββββββββββββββββββββββββ
if (numero % 2 == 0)
{
// Resto = 0 β PARI
lblRisultato.Text = $"{numero} Γ¨ un numero PARI β
";
lblRisultato.ForeColor = Color.Blue;
}
else
{
// Resto = 1 β DISPARI
lblRisultato.Text = $"{numero} Γ¨ un numero DISPARI β‘";
lblRisultato.ForeColor = Color.Red;
}
}
catch (FormatException)
{
// L'utente ha inserito testo non numerico
lblRisultato.Text = "β Inserisci un numero intero valido!";
lblRisultato.ForeColor = Color.Black;
}
catch (OverflowException)
{
// Il numero Γ¨ troppo grande per un int
lblRisultato.Text = "β Numero troppo grande!";
lblRisultato.ForeColor = Color.Black;
}
catch (Exception ex)
{
lblRisultato.Text = "β Errore: " + ex.Message;
lblRisultato.ForeColor = Color.Black;
}
}
}
}
π Analisi Operatore Modulo (%):
// L'operatore % restituisce il RESTO della divisione
int numero = 10;
int resto = numero % 2; // 10 diviso 2 = 5 con resto 0
// resto = 0
int numero2 = 7;
int resto2 = numero2 % 2; // 7 diviso 2 = 3 con resto 1
// resto2 = 1
// Altri esempi:
10 % 3 = 1 // 10 / 3 = 3 resto 1
15 % 4 = 3 // 15 / 4 = 3 resto 3
20 % 5 = 0 // 20 / 5 = 4 resto 0 (divisibile perfettamente)
Il modulo Γ¨ utile per verificare divisibilitΓ : se numero % divisore == 0,
il numero Γ¨ divisibile perfettamente.
- Miglioramento: Filtrare Input con KeyPress
Aggiungiamo l'evento KeyPress per permettere solo numeri e il segno meno
(per numeri negativi). Questo previene errori prima ancora che l'utente clicchi "Verifica".
Form1.cs - Evento KeyPress
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// EVENTO: KeyPress - Filtra caratteri non numerici
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
private void txtNumero_KeyPress(object sender, KeyPressEventArgs e)
{
// char.IsControl() verifica se Γ¨ un tasto di controllo (Backspace, Tab, ecc.)
// char.IsDigit() verifica se Γ¨ una cifra (0-9)
bool isNumero = char.IsDigit(e.KeyChar);
bool isControllo = char.IsControl(e.KeyChar);
bool isMeno = e.KeyChar == '-';
// Permetti SOLO:
// - Numeri (0-9)
// - Tasti di controllo (Backspace, Delete, ecc.)
// - Segno meno (-)
if (!isNumero && !isControllo && !isMeno)
{
e.Handled = true; // β Blocca il tasto
return;
}
// Permetti il segno meno SOLO all'inizio
if (isMeno)
{
TextBox txt = (TextBox)sender;
// Se il segno meno non Γ¨ all'inizio o c'Γ¨ giΓ un meno
if (txt.Text.IndexOf('-') > -1 || txt.SelectionStart != 0)
{
e.Handled = true; // β Blocca
}
}
}
β‘ Come Collegare l'Evento KeyPress:
- Seleziona
txtNumeronel Designer - F4 β Fulmine β‘ β Trova KeyPress
- Fai doppio click su KeyPress
- Scrivi il codice sopra nel metodo generato
π¬ Cosa Succede con KeyPress:
- Utente prova a scrivere "a" β KeyPress si attiva
char.IsDigit('a')= falsechar.IsControl('a')= false'a' == '-'= falsee.Handled = trueβ β "a" viene bloccato!- Utente prova a scrivere "5" β
char.IsDigit('5')= true - Tasto permesso β β "5" viene inserito in txtNumero
Nuovi Metodi e Concetti - Esercizio 2
Convert.ToInt32(string)
Converte una stringa in numero intero a 32 bit (int). Non accetta decimali.
// Sintassi:
int numero = Convert.ToInt32(stringa);
// Esempi:
Convert.ToInt32("123") // 123
Convert.ToInt32("-45") // -45
Convert.ToInt32("0") // 0
Convert.ToInt32("12.5") // β FormatException (ha decimali!)
Convert.ToInt32("abc") // β FormatException
// Differenza con ToDouble():
Convert.ToDouble("12.5") // β
12.5 (accetta decimali)
Convert.ToInt32("12.5") // β Errore (non accetta decimali)
// Quando usare ToInt32 vs ToDouble:
// ToInt32 β EtΓ , quantitΓ , contatori (numeri interi)
// ToDouble β Peso, altezza, prezzi (numeri decimali)
Operatore % (Modulo)
Restituisce il resto della divisione tra due numeri. Fondamentale per verificare divisibilitΓ .
// Sintassi:
int resto = dividendo % divisore;
// Esempi:
10 % 2 = 0 // 10 / 2 = 5 resto 0
10 % 3 = 1 // 10 / 3 = 3 resto 1
15 % 4 = 3 // 15 / 4 = 3 resto 3
20 % 5 = 0 // 20 / 5 = 4 resto 0
// Applicazioni pratiche:
// 1. Verificare se pari o dispari:
if (numero % 2 == 0)
Console.WriteLine("Pari");
// 2. Verificare se multiplo di 3:
if (numero % 3 == 0)
Console.WriteLine("Multiplo di 3");
// 3. Alternare colori in una lista (pari=blu, dispari=rosso):
if (indice % 2 == 0)
colore = Color.Blue;
else
colore = Color.Red;
if-else (Struttura Condizionale)
Esegue blocchi di codice diversi in base a una condizione booleana (true/false).
// Struttura base:
if (condizione)
{
// Eseguito se condizione Γ¨ true
}
else
{
// Eseguito se condizione Γ¨ false
}
// Esempio pratico:
int eta = 18;
if (eta >= 18)
{
MessageBox.Show("Maggiorenne");
}
else
{
MessageBox.Show("Minorenne");
}
// if-else if-else (condizioni multiple):
int voto = 85;
if (voto >= 90)
{
lblGiudizio.Text = "Eccellente";
}
else if (voto >= 80)
{
lblGiudizio.Text = "Ottimo";
}
else if (voto >= 70)
{
lblGiudizio.Text = "Buono";
}
else
{
lblGiudizio.Text = "Sufficiente";
}
Control.ForeColor (proprietΓ )
ProprietΓ che imposta il colore del testo di un controllo.
// Sintassi:
controllo.ForeColor = Color.NomeColore;
// Colori predefiniti:
lblRisultato.ForeColor = Color.Red;
lblRisultato.ForeColor = Color.Green;
lblRisultato.ForeColor = Color.Blue;
lblRisultato.ForeColor = Color.Orange;
lblRisultato.ForeColor = Color.Black;
lblRisultato.ForeColor = Color.Gray;
// Colore personalizzato RGB:
lblRisultato.ForeColor = Color.FromArgb(255, 100, 50);
// FromArgb(rosso, verde, blu) - valori da 0 a 255
// Uso pratico con feedback:
if (valido)
{
lblMessaggio.Text = "β
Corretto!";
lblMessaggio.ForeColor = Color.Green;
}
else
{
lblMessaggio.Text = "β Errore!";
lblMessaggio.ForeColor = Color.Red;
}
char.IsDigit() / char.IsControl()
Metodi statici per verificare il tipo di carattere.
// char.IsDigit(char) - verifica se Γ¨ una cifra (0-9)
char.IsDigit('5') // true
char.IsDigit('a') // false
char.IsDigit(' ') // false
// char.IsControl(char) - verifica se Γ¨ un carattere di controllo
char.IsControl('\b') // true (backspace)
char.IsControl('\t') // true (tab)
char.IsControl('a') // false
// char.IsLetter(char) - verifica se Γ¨ una lettera
char.IsLetter('M') // true
char.IsLetter('5') // false
// Uso in KeyPress:
private void txt_KeyPress(object sender, KeyPressEventArgs e)
{
// Permetti solo numeri e backspace
if (!char.IsDigit(e.KeyChar) && !char.IsControl(e.KeyChar))
{
e.Handled = true; // Blocca
}
}
string.IndexOf(char)
Restituisce la posizione (indice) della prima occorrenza di un carattere nella stringa. Ritorna -1 se non trovato.
// Sintassi:
int posizione = stringa.IndexOf(carattere);
// Esempi:
"Hello".IndexOf('e') // 1 (posizione 0=H, 1=e)
"Hello".IndexOf('o') // 4
"Hello".IndexOf('x') // -1 (non trovato)
"mario@email.com".IndexOf('@') // 5
// Uso pratico - verificare se contiene un carattere:
if (txtNumero.Text.IndexOf('-') > -1)
{
// La stringa contiene il segno meno
}
// Alternativa piΓΉ leggibile:
if (txtNumero.Text.Contains("-"))
{
// Stesso risultato, sintassi piΓΉ chiara
}
TextBox.SelectionStart (proprietΓ )
ProprietΓ che indica la posizione del cursore nella TextBox (indice del carattere).
// Posizione cursore:
txtNome.SelectionStart // 0 = inizio, 5 = dopo 5 caratteri
// Esempio - permetti '-' solo all'inizio:
if (e.KeyChar == '-' && txtNumero.SelectionStart != 0)
{
e.Handled = true; // Blocca se non Γ¨ all'inizio
}
// Spostare il cursore programmaticamente:
txtNome.SelectionStart = 0; // Cursore all'inizio
txtNome.SelectionStart = txtNome.Text.Length; // Cursore alla fine
Esercizio 3: Valutazione del Voto con Switch
Obiettivo
Creare un'applicazione che converte un voto numerico (0-100) in una valutazione letterale
(Eccellente, Molto Buono, Buono, Sufficiente, Insufficiente). Introduce la struttura
switch come alternativa a lunghe catene di if-else.
π― Nuovi Concetti:
- β
Struttura
switchper valutare condizioni multiple - β
Pattern matching con range (
>= e <) - β Combinare validazione e logica complessa
- β Feedback colorato dinamico basato su valutazione
π Scala di Valutazione:
| Voto Numerico | Valutazione | Colore |
|---|---|---|
| 90 - 100 | ECCELLENTE | β Verde |
| 80 - 89 | MOLTO BUONO | β Verde Scuro |
| 70 - 79 | BUONO | β Blu |
| 60 - 69 | SUFFICIENTE | β Arancione |
| 0 - 59 | INSUFFICIENTE | β Rosso |
- Progettazione dell'Interfaccia
| Tipo | Name | Text | Note |
|---|---|---|---|
| Label | lblTitolo | "Inserisci il Voto (0-100):" | - |
| TextBox | txtVoto |
vuoto | Input voto numerico |
| Button | btnValuta |
"Valuta" | - |
| Label | lblValutazione |
vuoto | Font: 16pt, Bold |
- Codice con Switch Statement
Form1.cs - Valutazione con Switch
using System;
using System.Drawing;
using System.Windows.Forms;
namespace ValutazioneVoto
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// EVENTO: Click del pulsante "Valuta"
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
private void btnValuta_Click(object sender, EventArgs e)
{
// βββββββββββββββββββββββββββββββββββββββββββββββββ
// STEP 1: Validazione campo vuoto
// βββββββββββββββββββββββββββββββββββββββββββββββββ
if (string.IsNullOrEmpty(txtVoto.Text))
{
lblValutazione.Text = "β οΈ Inserisci un voto!";
lblValutazione.ForeColor = Color.Gray;
return;
}
try
{
// βββββββββββββββββββββββββββββββββββββββββββββ
// STEP 2: Conversione e validazione range
// βββββββββββββββββββββββββββββββββββββββββββββ
int voto = Convert.ToInt32(txtVoto.Text);
// Validazione: voto deve essere tra 0 e 100
if (voto < 0 || voto > 100)
{
lblValutazione.Text = "β Il voto deve essere tra 0 e 100!";
lblValutazione.ForeColor = Color.Black;
return;
}
// βββββββββββββββββββββββββββββββββββββββββββββ
// STEP 3: Valutazione con SWITCH (C# 9.0+)
// βββββββββββββββββββββββββββββββββββββββββββββ
string valutazione;
Color colore;
// Switch con pattern matching (range)
switch (voto)
{
case >= 90 and <= 100: valutazione = "ECCELLENTE π"; colore = Color.Green; break; case >= 80 and < 90: valutazione = "MOLTO BUONO β"; colore = Color.DarkGreen; break; case >= 70 and < 80: valutazione = "BUONO β
"; colore = Color.Blue; break; case >= 60 and < 70: valutazione = "SUFFICIENTE βοΈ"; colore = Color.Orange; break; case >= 0 and < 60:
valutazione = "INSUFFICIENTE β";
colore = Color.Red;
break;
default:
// Questo non dovrebbe mai verificarsi grazie alla validazione sopra
valutazione = "Voto non valido";
colore = Color.Black;
break;
}
// βββββββββββββββββββββββββββββββββββββββββββββ
// STEP 4: Visualizzazione risultato
// βββββββββββββββββββββββββββββββββββββββββββββ
lblValutazione.Text = $"Voto {voto}: {valutazione}";
lblValutazione.ForeColor = colore;
}
catch (FormatException)
{
lblValutazione.Text = "β Inserisci un voto numerico valido!";
lblValutazione.ForeColor = Color.Black;
}
catch (Exception ex)
{
lblValutazione.Text = "β Errore: " + ex.Message;
lblValutazione.ForeColor = Color.Black;
}
}
}
}
π NOTA: Versione Compatibile per Visual Studio Vecchio
Il codice sopra usa il pattern matching di C# 9.0+
(case >= 90 and <= 100). Se il tuo Visual Studio non lo supporta,
usa questa versione alternativa con if-else:
Versione Compatibile (if-else)
// Versione con if-else (funziona su tutte le versioni C#)
string valutazione;
Color colore;
if (voto >= 90 && voto <= 100) { valutazione = "ECCELLENTE π"; colore = Color.Green; } else if (voto >= 80 && voto < 90) { valutazione = "MOLTO BUONO β"; colore = Color.DarkGreen; } else if (voto >= 70 && voto < 80) { valutazione = "BUONO β
"; colore = Color.Blue; } else if (voto >= 60 && voto < 70)
{
valutazione = "SUFFICIENTE βοΈ";
colore = Color.Orange;
}
else // voto < 60
{
valutazione = "INSUFFICIENTE β";
colore = Color.Red;
}
lblValutazione.Text = $"Voto {voto}: {valutazione}";
lblValutazione.ForeColor = colore;
π Confronto: Switch vs If-Else
β Quando usare SWITCH:
- Quando hai molte condizioni basate sullo stesso valore
- Quando le condizioni sono discrete (valori specifici o range)
- Codice piΓΉ leggibile con molti casi
β Quando usare IF-ELSE:
- Quando le condizioni sono complesse (piΓΉ variabili)
- Quando hai poche condizioni (2-3)
- Quando usi il pattern matching moderno (
>= and <) non supportato
// Switch moderno (C# 9.0+) - Elegante per range
switch (voto)
{
case >= 90 and <= 100: // ... break; } // If-else - PiΓΉ verboso ma universale if (voto >= 90 && voto <= 100)
{
// ...
}
// Switch classico - Solo per valori esatti
switch (giorno)
{
case 1:
nome = "Lunedì";
break;
case 2:
nome = "Martedì";
break;
}
- Validazione Avanzata con KeyPress
Form1.cs - KeyPress per Voto
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// EVENTO: KeyPress - Permetti solo numeri 0-9
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
private void txtVoto_KeyPress(object sender, KeyPressEventArgs e)
{
// Permetti solo numeri e backspace (NO segno meno)
if (!char.IsDigit(e.KeyChar) && !char.IsControl(e.KeyChar))
{
e.Handled = true; // Blocca il tasto
}
}
Nuovi Concetti - Esercizio 3
switch Statement
Struttura di controllo per eseguire codice diverso in base al valore di un'espressione.
// Sintassi base:
switch (variabile)
{
case valore1:
// Codice se variabile == valore1
break;
case valore2:
// Codice se variabile == valore2
break;
default:
// Codice se nessun case corrisponde
break;
}
// Esempio: giorni della settimana
int giorno = 3;
string nomeGiorno;
switch (giorno)
{
case 1:
nomeGiorno = "Lunedì";
break;
case 2:
nomeGiorno = "Martedì";
break;
case 3:
nomeGiorno = "Mercoledì";
break;
default:
nomeGiorno = "Giorno non valido";
break;
}
// IMPORTANTE: break Γ¨ obbligatorio!
// Senza break il programma NON si compila (errore CS0163):
// in C#, a differenza di C e Java, un case non puΓ² "cadere" nel successivo
Pattern Matching con Range (C# 9.0+)
Sintassi moderna per verificare se un valore rientra in un intervallo usando and.
// Sintassi moderna:
switch (numero)
{
case >= 90 and <= 100: // numero Γ¨ tra 90 e 100 (inclusi) break; case >= 80 and < 90: // numero Γ¨ tra 80 e 89 break; } // Equivalente con if-else: if (numero >= 90 && numero <= 100) { // ... } else if (numero >= 80 && numero < 90) { // ... } // Altri pattern: switch (valore) { case > 0: // maggiore di 0
break;
case < 0: // minore di 0
break;
case 0: // uguale a 0
break;
}
β οΈ CompatibilitΓ : Questa sintassi richiede C# 9.0+ (Visual Studio 2019 16.8 o successivo).
Se non disponibile, usa if-else.
Operatore && (AND Logico)
Restituisce true solo se TUTTE le condizioni sono vere.
// Tabella di veritΓ :
true && true // true
true && false // false
false && false // false
// Uso per validare range:
if (voto >= 0 && voto <= 100) { // voto Γ¨ valido solo se >= 0 E <= 100 } // Differenza con || (OR): // && β TUTTE devono essere vere // || β ALMENO UNA deve essere vera // Esempio pratico: if (eta >= 18 && patente == true)
{
// PuΓ² guidare SOLO se ha 18 anni E ha la patente
}
// Condizioni multiple:
if (nome != "" && cognome != "" && email.Contains("@"))
{
// Tutti e 3 devono essere veri
}
break Statement
Interrompe l'esecuzione di un blocco switch o di un ciclo.
// In switch - OBBLIGATORIO dopo ogni case:
switch (valore)
{
case 1:
Console.WriteLine("Uno");
break; // Esce dallo switch
case 2:
Console.WriteLine("Due");
break; // Senza break, errore di compilazione!
}
// In cicli (vedremo nelle prossime lezioni):
for (int i = 0; i < 10; i++)
{
if (i == 5)
break; // Esce dal ciclo quando i Γ¨ 5
}
// Cosa succede SENZA break?
switch (valore)
{
case 1:
Console.WriteLine("Uno");
// β ERRORE DI COMPILAZIONE: manca break!
// In C# il codice NON puΓ² "cadere" nel case successivo:
// Visual Studio sottolinea in rosso e il programma non parte
case 2:
Console.WriteLine("Due");
break;
}
Esercizio 4: Calcolatrice con 4 Operazioni
Obiettivo
Creare una calcolatrice completa che esegue le quattro operazioni fondamentali (somma, sottrazione, moltiplicazione, divisione) con gestione completa degli errori, inclusa la divisione per zero.
π― Cosa Imparerai:
- β Gestire piΓΉ operazioni con un unico metodo helper
- β Validazione avanzata (divisione per zero)
- β Abilitare/disabilitare pulsanti dinamicamente
- β Organizzare codice con metodi riutilizzabili
- β
Operatori aritmetici:
+,-,*,/
- Progettazione dell'Interfaccia
| Tipo | Name | Text | Note |
|---|---|---|---|
| Label | lblNumero1 | "Primo Numero:" | - |
| TextBox | txtNumero1 |
vuoto | - |
| Label | lblNumero2 | "Secondo Numero:" | - |
| TextBox | txtNumero2 |
vuoto | - |
| Button | btnSomma |
"+" | Enabled = false |
| Button | btnSottrai |
"-" | Enabled = false |
| Button | btnMoltiplica |
"Γ" | Enabled = false |
| Button | btnDividi |
"Γ·" | Enabled = false |
| Label | lblOperazione |
"Seleziona operazione" | Font: 10pt |
| Label | lblRisultato |
"" | Font: 16pt, Bold |
- Codice Completo della Calcolatrice
Form1.cs - Calcolatrice Completa
using System;
using System.Drawing;
using System.Windows.Forms;
namespace CalcolatriceCompleta
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// EVENTO FORM LOAD: Inizializzazione
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
private void Form1_Load(object sender, EventArgs e)
{
// Inizializza l'interfaccia all'avvio
lblOperazione.Text = "Seleziona un'operazione";
lblRisultato.Text = "";
// Disabilita tutti i pulsanti (abilitati quando i numeri sono validi)
AbilitaPulsanti(false);
}
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// EVENTI: Click dei pulsanti operazione
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
private void btnSomma_Click(object sender, EventArgs e)
{
CalcolaOperazione('+');
}
private void btnSottrai_Click(object sender, EventArgs e)
{
CalcolaOperazione('-');
}
private void btnMoltiplica_Click(object sender, EventArgs e)
{
CalcolaOperazione('*');
}
private void btnDividi_Click(object sender, EventArgs e)
{
CalcolaOperazione('/');
}
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// METODO PRINCIPALE: Calcola operazione
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
private void CalcolaOperazione(char operatore)
{
// Validazione campi
if (string.IsNullOrEmpty(txtNumero1.Text) ||
string.IsNullOrEmpty(txtNumero2.Text))
{
lblRisultato.Text = "β οΈ Inserisci entrambi i numeri!";
lblRisultato.ForeColor = Color.Red;
return;
}
try
{
// Conversione numeri
double num1 = Convert.ToDouble(txtNumero1.Text);
double num2 = Convert.ToDouble(txtNumero2.Text);
double risultato = 0;
bool operazioneValida = true;
string nomeOperazione = "";
// βββββββββββββββββββββββββββββββββββββββββββββ
// Esegui operazione in base al carattere
// βββββββββββββββββββββββββββββββββββββββββββββ
switch (operatore)
{
case '+':
risultato = num1 + num2;
nomeOperazione = "Somma";
break;
case '-':
risultato = num1 - num2;
nomeOperazione = "Sottrazione";
break;
case '*':
risultato = num1 * num2;
nomeOperazione = "Moltiplicazione";
break;
case '/':
// IMPORTANTE: Gestione divisione per zero
if (num2 != 0)
{
risultato = num1 / num2;
nomeOperazione = "Divisione";
}
else
{
lblRisultato.Text = "β Errore: divisione per zero!";
lblRisultato.ForeColor = Color.Red;
lblOperazione.Text = "Non puoi dividere per zero";
operazioneValida = false;
}
break;
}
// Mostra risultato se operazione valida
if (operazioneValida)
{
lblOperazione.Text = $"Operazione: {nomeOperazione}";
lblRisultato.Text = $"Risultato: {risultato:F2}";
lblRisultato.ForeColor = Color.Green;
}
}
catch (FormatException)
{
lblRisultato.Text = "β Inserisci valori numerici validi!";
lblRisultato.ForeColor = Color.Red;
}
catch (Exception ex)
{
lblRisultato.Text = $"β Errore: {ex.Message}";
lblRisultato.ForeColor = Color.Red;
}
}
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// EVENTI: TextChanged per validazione dinamica
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
private void txtNumero1_TextChanged(object sender, EventArgs e)
{
AbilitaPulsanti(ValidaInput());
}
private void txtNumero2_TextChanged(object sender, EventArgs e)
{
AbilitaPulsanti(ValidaInput());
}
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// METODO HELPER: Valida che entrambi i campi siano numeri
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
private bool ValidaInput()
{
try
{
if (!string.IsNullOrEmpty(txtNumero1.Text))
Convert.ToDouble(txtNumero1.Text);
if (!string.IsNullOrEmpty(txtNumero2.Text))
Convert.ToDouble(txtNumero2.Text);
return true;
}
catch
{
return false;
}
}
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// METODO HELPER: Abilita/disabilita pulsanti operazione
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
private void AbilitaPulsanti(bool abilita)
{
btnSomma.Enabled = abilita;
btnSottrai.Enabled = abilita;
btnMoltiplica.Enabled = abilita;
btnDividi.Enabled = abilita;
}
}
}
π Analisi del Design Pattern:
Nota come il codice Γ¨ organizzato in metodi riutilizzabili:
CalcolaOperazione(char operatore): Metodo generico che funziona per tutte le 4 operazioni. Riceve il simbolo dell'operazione come parametro.ValidaInput(): Metodo separato per validazione, riutilizzato in 2 punti diversi.AbilitaPulsanti(bool abilita): Metodo che abilita/disabilita tutti i 4 pulsanti con una sola chiamata.
Questo Γ¨ un esempio di codice DRY (Don't Repeat Yourself): scriviamo la logica una volta e la riusiamo dove serve!
β οΈ Gestione Divisione per Zero:
case '/':
if (num2 != 0)
{
risultato = num1 / num2;
}
else
{
// Divisione per zero = ERRORE MATEMATICO
lblRisultato.Text = "β Divisione per zero!";
operazioneValida = false;
}
break;
La divisione per zero Γ¨ un errore matematico (risultato = infinito, indefinito). Dobbiamo sempre controllare che il divisore sia diverso da zero prima di eseguire la divisione.
- π¬ Flusso di Esecuzione Completo
Scenario: Calcolare 10 + 5
- Avvio applicazione:
- Form1_Load si attiva
- Tutti i pulsanti vengono disabilitati (
Enabled = false)
- Utente scrive "10" in txtNumero1:
- Evento
txtNumero1_TextChanged - Chiama
ValidaInput()β txtNumero2 Γ¨ vuoto β return false AbilitaPulsanti(false)β Pulsanti ancora disabilitati
- Evento
- Utente scrive "5" in txtNumero2:
- Evento
txtNumero2_TextChanged - Chiama
ValidaInput()β Entrambi sono numeri β return true AbilitaPulsanti(true)β β Pulsanti si abilitano!
- Evento
- Utente clicca sul pulsante "+":
- Evento
btnSomma_Click - Chiama
CalcolaOperazione('+') - Converte: num1 = 10, num2 = 5
- Switch:
case '+'βrisultato = 10 + 5 = 15 - Mostra: "Risultato: 15.00" (verde)
- lblOperazione: "Operazione: Somma"
- Evento
Operatori Aritmetici in C#
Operatore + (Somma)
Somma due numeri. Con stringhe, concatena (unisce) le stringhe.
// Con numeri:
int risultato = 10 + 5; // 15
double somma = 3.5 + 2.1; // 5.6
// Con stringhe (concatenazione):
string nome = "Mario" + " " + "Rossi"; // "Mario Rossi"
string testo = "Voto: " + 85; // "Voto: 85"
Operatore - (Sottrazione)
Sottrae il secondo numero dal primo.
int risultato = 10 - 5; // 5
double differenza = 7.8 - 2.3; // 5.5
// Con numeri negativi:
int x = 10 - 15; // -5
Operatore * (Moltiplicazione)
Moltiplica due numeri.
int risultato = 10 * 5; // 50
double prodotto = 2.5 * 4; // 10.0
// Calcolo area rettangolo:
double larghezza = 5.0;
double altezza = 3.0;
double area = larghezza * altezza; // 15.0
Operatore / (Divisione)
Divide il primo numero per il secondo. ATTENZIONE: La divisione per zero genera errore!
double risultato = 10.0 / 2.0; // 5.0
double quoziente = 7.0 / 2.0; // 3.5
// IMPORTANTE: Divisione interi vs decimali
int a = 7 / 2; // 3 (divisione intera, perde decimali!)
double b = 7.0 / 2.0; // 3.5 (divisione decimale)
double c = 7 / 2; // 3.0 (converti almeno uno in double!)
// Gestione divisione per zero:
double divisore = 0;
if (divisore != 0)
{
double risultato = 10 / divisore;
}
else
{
// Errore: divisione per zero!
}
Precedenza Operatori
Gli operatori hanno un ordine di esecuzione (come in matematica).
// Ordine di precedenza (dal piΓΉ alto al piΓΉ basso):
// 1. Parentesi ()
// 2. Moltiplicazione * e Divisione /
// 3. Somma + e Sottrazione -
int risultato1 = 10 + 5 * 2; // 20 (prima 5*2=10, poi 10+10)
int risultato2 = (10 + 5) * 2; // 30 (prima 10+5=15, poi 15*2)
double calc = 10 + 20 / 2 - 3; // 17
// Esecuzione: 20/2=10 β 10+10=20 β 20-3=17
// Best Practice: Usa parentesi per chiarezza!
double media = (voto1 + voto2 + voto3) / 3; // β
Chiaro
double media2 = voto1 + voto2 + voto3 / 3; // β Confuso!
Esercizio 5: Convertitore di Temperatura
Obiettivo
Creare un convertitore che trasforma temperature da Celsius a Fahrenheit e viceversa. Introduce l'uso di RadioButton per selezionare opzioni mutuamente esclusive e formule matematiche piΓΉ complesse.
π― Nuovi Concetti:
- β RadioButton: Controlli per scelte esclusive (o questo o quello)
- β RadioButton.Checked: Verificare quale opzione Γ¨ selezionata
- β Formule matematiche: Applicare conversioni con precedenza operatori
- β CheckedChanged: Evento quando cambia selezione RadioButton
- β Aggiornamento dinamico dell'interfaccia
π Formule di Conversione:
π₯ Da Celsius a Fahrenheit:
F = C Γ 9/5 + 32
// Esempi:
0Β°C = 0 Γ 9/5 + 32 = 32Β°F (punto di congelamento acqua)
100Β°C = 100 Γ 9/5 + 32 = 212Β°F (punto di ebollizione acqua)
37Β°C = 37 Γ 9/5 + 32 = 98.6Β°F (temperatura corporea)
βοΈ Da Fahrenheit a Celsius:
C = (F - 32) Γ 5/9
// Esempi:
32Β°F = (32 - 32) Γ 5/9 = 0Β°C
212Β°F = (212 - 32) Γ 5/9 = 100Β°C
98.6Β°F = (98.6 - 32) Γ 5/9 = 37Β°C
- Progettazione dell'Interfaccia
| Tipo | Name | Text | Note |
|---|---|---|---|
| Label | lblTitolo |
"Convertitore di Temperatura" | Font: 14pt, Bold |
| Label | lblTemperatura | "Temperatura:" | - |
| TextBox | txtTemperatura |
vuoto | Input temperatura |
| Label | lblTipoConversione | "Tipo di Conversione:" | Font: Bold |
| RadioButton | rbCelsius |
"Celsius β Fahrenheit" | Checked = true |
| RadioButton | rbFahrenheit |
"Fahrenheit β Celsius" | Checked = false |
| Button | btnConverti |
"Converti" | - |
| Label | lblRisultato |
vuoto | Font: 14pt, Bold |
π‘ Suggerimento Layout:
Posiziona i due RadioButton uno sotto l'altro, vicini tra loro. Visual Studio raggruppa automaticamente i RadioButton sullo stesso Form/Panel: quando ne selezioni uno, l'altro si deseleziona automaticamente.
- Codice Completo del Convertitore
Form1.cs - Convertitore Temperatura
using System;
using System.Drawing;
using System.Windows.Forms;
namespace ConvertitoreTemperatura
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// EVENTO: Click del pulsante "Converti"
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
private void btnConverti_Click(object sender, EventArgs e)
{
// βββββββββββββββββββββββββββββββββββββββββββββββββ
// STEP 1: Validazione campo vuoto
// βββββββββββββββββββββββββββββββββββββββββββββββββ
if (string.IsNullOrEmpty(txtTemperatura.Text))
{
lblRisultato.Text = "β οΈ Inserisci una temperatura!";
lblRisultato.ForeColor = Color.Gray;
return;
}
try
{
// βββββββββββββββββββββββββββββββββββββββββββββ
// STEP 2: Conversione valore temperatura
// βββββββββββββββββββββββββββββββββββββββββββββ
double temperatura = Convert.ToDouble(txtTemperatura.Text);
double risultato;
string unitaPartenza;
string unitaArrivo;
// βββββββββββββββββββββββββββββββββββββββββββββ
// STEP 3: Determina tipo conversione con RadioButton
// βββββββββββββββββββββββββββββββββββββββββββββ
if (rbCelsius.Checked)
{
// Converti da Celsius a Fahrenheit
// Formula: F = C Γ 9/5 + 32
risultato = temperatura * 9.0 / 5.0 + 32;
unitaPartenza = "Β°C";
unitaArrivo = "Β°F";
}
else // rbFahrenheit.Checked
{
// Converti da Fahrenheit a Celsius
// Formula: C = (F - 32) Γ 5/9
risultato = (temperatura - 32) * 5.0 / 9.0;
unitaPartenza = "Β°F";
unitaArrivo = "Β°C";
}
// βββββββββββββββββββββββββββββββββββββββββββββ
// STEP 4: Visualizzazione risultato formattato
// βββββββββββββββββββββββββββββββββββββββββββββ
// Formato: "25Β°C = 77Β°F"
lblRisultato.Text = $"{temperatura:F1}{unitaPartenza} = {risultato:F1}{unitaArrivo}";
lblRisultato.ForeColor = Color.Blue;
}
catch (FormatException)
{
lblRisultato.Text = "β Inserisci un valore numerico valido!";
lblRisultato.ForeColor = Color.Red;
}
catch (Exception ex)
{
lblRisultato.Text = $"β Errore: {ex.Message}";
lblRisultato.ForeColor = Color.Red;
}
}
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// EVENTI: CheckedChanged - Quando cambia selezione RadioButton
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
private void rbCelsius_CheckedChanged(object sender, EventArgs e)
{
// Aggiorna l'interfaccia quando cambia la selezione
AggiornaInterfaccia();
}
private void rbFahrenheit_CheckedChanged(object sender, EventArgs e)
{
AggiornaInterfaccia();
}
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// METODO HELPER: Aggiorna testi interfaccia
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
private void AggiornaInterfaccia()
{
if (rbCelsius.Checked)
{
lblTitolo.Text = "π₯ Converti da Celsius a Fahrenheit";
lblTemperatura.Text = "Temperatura (Β°C):";
}
else
{
lblTitolo.Text = "βοΈ Converti da Fahrenheit a Celsius";
lblTemperatura.Text = "Temperatura (Β°F):";
}
// Pulisce il risultato precedente
lblRisultato.Text = "";
}
}
}
π Analisi delle Formule:
1οΈβ£ Celsius β Fahrenheit:
// Formula: F = C Γ 9/5 + 32
risultato = temperatura * 9.0 / 5.0 + 32;
// IMPORTANTE: Usa 9.0 e 5.0 (con decimali)!
// Sbagliato: 9/5 = 1 (divisione intera)
// Corretto: 9.0/5.0 = 1.8 (divisione decimale)
// Esempio: 25Β°C
risultato = 25 * 9.0 / 5.0 + 32
= 25 * 1.8 + 32
= 45 + 32
= 77Β°F
2οΈβ£ Fahrenheit β Celsius:
// Formula: C = (F - 32) Γ 5/9
risultato = (temperatura - 32) * 5.0 / 9.0;
// IMPORTANTE: Parentesi sono fondamentali!
// Sbagliato: temperatura - 32 * 5.0 / 9.0
// (moltiplicazione prima della sottrazione)
// Corretto: (temperatura - 32) * 5.0 / 9.0
// (sottrazione prima, poi moltiplicazione)
// Esempio: 77Β°F
risultato = (77 - 32) * 5.0 / 9.0
= 45 * 5.0 / 9.0
= 225.0 / 9.0
= 25Β°C
π‘ PerchΓ© 9.0 e 5.0 invece di 9 e 5?
In C#, la divisione tra numeri interi produce un risultato intero (perde i decimali):
// Divisione INTERA (entrambi int):
int a = 9 / 5; // 1 (perde .8)
int b = 7 / 2; // 3 (perde .5)
// Divisione DECIMALE (almeno uno Γ¨ double):
double c = 9.0 / 5.0; // 1.8 β
double d = 9.0 / 5; // 1.8 β
(basta uno double)
double e = 9 / 5.0; // 1.8 β
// Nel convertitore:
// β SBAGLIATO (perde decimali):
risultato = temperatura * 9 / 5 + 32;
// 25 * 9 / 5 + 32 = 25 * 1 + 32 = 57 (ERRORE!)
// β
CORRETTO (mantiene decimali):
risultato = temperatura * 9.0 / 5.0 + 32;
// 25 * 9.0 / 5.0 + 32 = 25 * 1.8 + 32 = 77
-
π¬ Flusso di Esecuzione: Convertire 0Β°C
-
Avvio applicazione:
- rbCelsius Γ¨ selezionato di default (Checked = true)
- lblTitolo: "π₯ Converti da Celsius a Fahrenheit"
-
Utente scrive "0" in txtTemperatura
-
Utente clicca "Converti":
- Evento
btnConverti_Click - Validazione: campo non vuoto β
- Conversione:
temperatura = 0 - Verifica:
rbCelsius.Checked= true - Calcolo:
risultato = 0 * 9.0 / 5.0 + 32 = 32 - Mostra: "0.0Β°C = 32.0Β°F" (blu)
- Evento
-
Utente clicca su rbFahrenheit:
- Evento
rbFahrenheit_CheckedChanged - rbCelsius automaticamente diventa Checked = false
- Chiama
AggiornaInterfaccia() - lblTitolo: "βοΈ Converti da Fahrenheit a Celsius"
- lblRisultato: "" (pulito)
- Evento
-
Utente scrive "32" e clicca "Converti":
- temperatura = 32
- Verifica:
rbFahrenheit.Checked= true - Calcolo:
risultato = (32 - 32) * 5.0 / 9.0 = 0 - Mostra: "32.0Β°F = 0.0Β°C" (blu)
Nuovi Controlli e Concetti - Esercizio 5
RadioButton
Controllo per selezionare una sola opzione tra un gruppo di scelte mutuamente esclusive.
// Caratteristiche RadioButton:
// 1. Solo UNO puΓ² essere selezionato alla volta
// 2. Selezionarne uno deseleziona automaticamente gli altri
// 3. Devono essere nello stesso contenitore (Form, Panel, GroupBox)
// Creazione:
RadioButton rbOpzione1 = new RadioButton();
rbOpzione1.Text = "Opzione 1";
rbOpzione1.Checked = true; // Selezionato
RadioButton rbOpzione2 = new RadioButton();
rbOpzione2.Text = "Opzione 2";
rbOpzione2.Checked = false; // Non selezionato
// Verifica quale Γ¨ selezionato:
if (rbOpzione1.Checked)
{
// L'utente ha selezionato Opzione 1
}
else if (rbOpzione2.Checked)
{
// L'utente ha selezionato Opzione 2
}
RadioButton.Checked (proprietΓ )
ProprietΓ booleana che indica se il RadioButton Γ¨ selezionato (true) o no (false).
// Leggere lo stato:
bool selezionato = rbCelsius.Checked;
// Impostare lo stato programmaticamente:
rbCelsius.Checked = true; // Seleziona questo
// Automaticamente rbFahrenheit diventa Checked = false
// Uso pratico:
if (rbCelsius.Checked)
{
// Esegui conversione Celsius β Fahrenheit
}
else
{
// Esegui conversione Fahrenheit β Celsius
}
Evento CheckedChanged
Si attiva quando cambia lo stato Checked del RadioButton (da true a false o viceversa).
// Gestione evento:
private void rbCelsius_CheckedChanged(object sender, EventArgs e)
{
// Questo si attiva quando:
// - L'utente clicca su rbCelsius (diventa Checked = true)
// - L'utente clicca su rbFahrenheit (rbCelsius diventa Checked = false)
if (rbCelsius.Checked)
{
lblTitolo.Text = "Converti da Celsius";
}
}
// ATTENZIONE: Si attiva due volte quando cambi selezione:
// 1. Sul RadioButton che si DESELEZIONA (Checked passa da true a false)
// 2. Sul RadioButton che si SELEZIONA (Checked passa da false a true)
// Best Practice: Controlla sempre rbX.Checked prima di agire
private void RadioButton_CheckedChanged(object sender, EventArgs e)
{
RadioButton rb = (RadioButton)sender;
if (rb.Checked) // Esegui solo se Γ¨ quello selezionato
{
// Logica qui
}
}
Formattazione :F1
Formatta un numero con 1 cifra decimale. Variante di :F2 visto negli esercizi precedenti.
double temperatura = 25.6789;
// Vari formati decimali:
$"{temperatura:F0}" // "26" (nessun decimale, arrotondato)
$"{temperatura:F1}" // "25.7" (1 decimale)
$"{temperatura:F2}" // "25.68" (2 decimali)
$"{temperatura:F3}" // "25.679" (3 decimali)
// Nel convertitore:
lblRisultato.Text = $"{temperatura:F1}Β°C = {risultato:F1}Β°F";
// Output: "25.7Β°C = 78.3Β°F"
// Alternativa senza formattazione:
lblRisultato.Text = temperatura + "Β°C = " + risultato + "Β°F";
// Output: "25.6789Β°C = 78.22202Β°F" (troppi decimali!)
String Interpolation $"..."
Sintassi moderna per inserire variabili direttamente in una stringa usando ${variabile}.
// Metodo MODERNO (C# 6.0+) - String Interpolation:
string nome = "Mario";
int eta = 25;
string messaggio = $"Ciao {nome}, hai {eta} anni";
// Output: "Ciao Mario, hai 25 anni"
// Con formattazione:
double prezzo = 19.99;
string testo = $"Prezzo: β¬{prezzo:F2}";
// Output: "Prezzo: β¬19.99"
// Metodo VECCHIO - Concatenazione:
string messaggio2 = "Ciao " + nome + ", hai " + eta + " anni";
// Stesso risultato ma meno leggibile
// Metodo VECCHIO - String.Format:
string messaggio3 = String.Format("Ciao {0}, hai {1} anni", nome, eta);
// Best Practice: Usa String Interpolation $"..." quando possibile!
lblRisultato.Text = $"{temperatura:F1}Β°C = {risultato:F1}Β°F";
Precedenza con Parentesi
Le parentesi forzano l'ordine di esecuzione delle operazioni matematiche.
// CRUCIALE nelle formule di conversione!
// β SBAGLIATO (senza parentesi):
risultato = temperatura - 32 * 5.0 / 9.0;
// Esecuzione: 32 * 5.0 = 160.0
// 160.0 / 9.0 = 17.78
// temperatura - 17.78
// Per 77Β°F: 77 - 17.78 = 59.22 (ERRORE! Dovrebbe essere 25)
// β
CORRETTO (con parentesi):
risultato = (temperatura - 32) * 5.0 / 9.0;
// Esecuzione: (77 - 32) = 45
// 45 * 5.0 = 225.0
// 225.0 / 9.0 = 25.0 (CORRETTO!)
// Regola: Le parentesi hanno MASSIMA precedenza
// Ordine senza parentesi: * / % β + -
// Con parentesi: () β * / % β + -
// Altri esempi:
int x = 10 + 5 * 2; // 20 (prima 5*2=10, poi +10)
int y = (10 + 5) * 2; // 30 (prima 10+5=15, poi 15*2)
double z = 10 + 20 / 2; // 20 (prima 20/2=10, poi 10+10)
double w = (10 + 20) / 2; // 15 (prima 10+20=30, poi 30/2)
Riepilogo Completo: Cosa Hai Imparato
Competenze Acquisite in Questa Lezione
π’ Operazioni Matematiche
- Somma (
+), sottrazione (-) - Moltiplicazione (
*), divisione (/) - Modulo (
%) per resto divisione - Precedenza operatori e uso parentesi
β Strutture Condizionali
if-elseper decisioni binarieif-else if-elseper condizioni multipleswitchper valutazioni discrete- Pattern matching con range (C# 9.0+)
π Conversioni di Tipo
Convert.ToDouble()per decimaliConvert.ToInt32()per interi.ToString()per stringhe- Formattazione con
:F0,:F1,:F2
π‘οΈ Validazione Input
string.IsNullOrEmpty()- Gestione errori con
try-catch - Validazione range (es: 0-100)
- Filtro caratteri con
KeyPress
π¨ Feedback Visivo
- Cambiare colori con
ForeColor - Abilitare/disabilitare con
Enabled - Messaggi dinamici informativi
- Icone emoji per UX migliore
ποΈ Nuovi Controlli
- RadioButton: Scelte mutuamente esclusive
.Checkedper verificare selezione- Evento
CheckedChanged - Aggiornamento dinamico interfaccia
π Tabella Riepilogativa Esercizi
| Esercizio | Concetti Chiave | Applicazione Pratica |
|---|---|---|
| 1. Somma Numeri | Conversioni, validazione, try-catch | Base per qualsiasi calcolatrice |
| 2. Pari/Dispari | Operatore %, if-else, KeyPress | Validazione numeri, filtri input |
| 3. Valutazione Voto | Switch, pattern matching, range | Sistemi di rating, classificazione |
| 4. Calcolatrice | 4 operatori, metodi helper, divisione zero | App calcolatrice completa |
| 5. Convertitore Temp | RadioButton, formule complesse, precedenza | Convertitori unitΓ di misura |
Best Practices: Lezioni Apprese
Regole d'Oro della Programmazione
1οΈβ£ Valida SEMPRE l'Input Utente
Non fidarti mai di ciΓ² che l'utente inserisce. Controlla sempre:
- β
Il campo Γ¨ compilato? (
string.IsNullOrEmpty()) - β
Il valore Γ¨ numerico? (
try-catchoTryParse) - β
Γ nel range corretto? (
if (voto >= 0 && voto <= 100)) - β Casi speciali? (divisione per zero, valori negativi, ecc.)
2οΈβ£ Dai Feedback Visivo Immediato
L'utente deve sempre sapere cosa sta succedendo:
- π’ Verde: Operazione riuscita, valore valido
- π΄ Rosso: Errore, valore non valido
- π Arancione: Avviso, attenzione richiesta
- π΅ Blu: Informazione neutra, risultato
- βͺ Grigio: Disabilitato, non disponibile
3οΈβ£ Scrivi Codice Leggibile
// β
BUONO - Leggibile
if (eta >= 18)
{
MessageBox.Show("Maggiorenne");
}
else
{
MessageBox.Show("Minorenne");
}
// β CATTIVO - Compresso, illeggibile
if(eta>=18)MessageBox.Show("Maggiorenne");else MessageBox.Show("Minorenne");
// β
BUONO - Nomi significativi
double temperaturaFahrenheit = (celsius * 9.0 / 5.0) + 32;
// β CATTIVO - Nomi vaghi
double x = (y * 9.0 / 5.0) + 32;
4οΈβ£ Usa try-catch per Conversioni
// β
BUONO - Gestisce errori
try
{
int numero = Convert.ToInt32(txtInput.Text);
// Usa numero sapendo che Γ¨ valido
}
catch (FormatException)
{
lblErrore.Text = "Inserisci un numero valido!";
}
// β CATTIVO - PuΓ² crashare
int numero = Convert.ToInt32(txtInput.Text); // π₯ Se non Γ¨ numero, crash!
5οΈβ£ Attenzione ai Decimali nelle Divisioni
// β SBAGLIATO - Divisione intera perde decimali
double media = (voto1 + voto2 + voto3) / 3;
// Se voto1=7, voto2=8, voto3=9 β (7+8+9)/3 = 24/3 = 8 (CORRETTO)
// Se voto1=7, voto2=8, voto3=8 β (7+8+8)/3 = 23/3 = 7 (ERRORE! Dovrebbe essere 7.67)
// β
CORRETTO - Almeno un operando deve essere double
double media = (voto1 + voto2 + voto3) / 3.0;
// 23 / 3.0 = 7.666... β
// Oppure converti esplicitamente:
double media = (double)(voto1 + voto2 + voto3) / 3;
6οΈβ£ Usa Parentesi nelle Formule Complesse
Anche se conosci la precedenza degli operatori, le parentesi rendono il codice piΓΉ chiaro:
// β
CHIARO - Parentesi esplicite
double fahrenheit = (celsius * 9.0 / 5.0) + 32;
double media = (voto1 + voto2 + voto3) / 3.0;
// β AMBIGUO - Precedenza implicita
double fahrenheit = celsius * 9.0 / 5.0 + 32; // Funziona ma meno chiaro
double media = voto1 + voto2 + voto3 / 3.0; // π₯ ERRORE! Divide solo voto3
Errori Comuni da Evitare
1οΈβ£ Dimenticare la Gestione Errori
// β PERICOLOSO
private void btnCalcola_Click(object sender, EventArgs e)
{
double num = Convert.ToDouble(txtNumero.Text); // π₯ Crash se non Γ¨ numero!
lblRisultato.Text = (num * 2).ToString();
}
// β
SICURO
private void btnCalcola_Click(object sender, EventArgs e)
{
try
{
double num = Convert.ToDouble(txtNumero.Text);
lblRisultato.Text = (num * 2).ToString();
}
catch (FormatException)
{
lblRisultato.Text = "Inserisci un numero valido!";
}
}
2οΈβ£ Non Validare la Divisione per Zero
// β ERRORE - Divisione per zero
double risultato = num1 / num2; // π₯ Se num2 = 0, errore!
// β
CORRETTO - Controllo prima di dividere
if (num2 != 0)
{
double risultato = num1 / num2;
lblRisultato.Text = risultato.ToString();
}
else
{
lblRisultato.Text = "Errore: divisione per zero!";
}
3οΈβ£ Confondere = con ==
// β ERRORE - Assegnazione invece di confronto
if (voto = 10) // π₯ ERRORE! Sta assegnando, non confrontando!
{
// Questo codice non compila
}
// β
CORRETTO - Confronto
if (voto == 10) // β
Confronta se voto Γ¨ uguale a 10
{
lblGiudizio.Text = "Perfetto!";
}
// Ricorda:
// = β Assegnazione (voto = 10 β assegna 10 a voto)
// == β Confronto (voto == 10 β verifica se voto Γ¨ 10)
4οΈβ£ Dimenticare break in switch
// β ERRORE - Manca break
switch (voto)
{
case >= 90:
valutazione = "Eccellente";
// β ERRORE: manca break!
case >= 80:
valutazione = "Molto Buono";
break;
}
// β
CORRETTO - break dopo ogni case
switch (voto)
{
case >= 90:
valutazione = "Eccellente";
break; // β
case >= 80:
valutazione = "Molto Buono";
break; // β
}
Prossimi Passi: Il Tuo Percorso di Apprendimento
Cosa Farai Nella Prossima Lezione
Ripetere e riutilizzare: cicli e metodi
- π Ciclo for: ripetere codice un numero preciso di volte (tabelline, somme)
- βΎοΈ while e do-while: ripetere finchΓ© serve
- π§ Campi del form: ricordare un valore tra un clic e l'altro
- βοΈ Metodi tuoi: parametri e return, per non copiare lo stesso codice in piΓΉ bottoni
π― Il Piano Completo del Corso
Nelle prossime lezioni passerai da un valore alla volta a elenchi di dati (ListBox, ComboBox, List), poi agli oggetti (Parco Auto) fino al progetto finale Gestionale Biblioteca. Per la teoria di cicli, array e metodi trovi le lezioni del percorso C# β il linguaggio.
πͺ Esercitazione Prima della Prossima Lezione
Per consolidare quanto appreso, prova a completare questi esercizi:
- Calcolatrice IMC Migliorata: Riprendi la calcolatrice IMC e aggiungi classificazione BMI con colori (come nell'Esercizio 3 - Valutazione Voto)
- Convertitore Multi-UnitΓ : Estendi il convertitore temperatura aggiungendo conversioni per: km β miglia, kg β libbre, litri β galloni
- Calcolatrice Scientifica Semplice: Aggiungi alla calcolatrice base (Esercizio 4): potenza (xΒ²), radice quadrata (β), percentuale (%)
- Sistema di Voti: Crea un'app che permette di inserire piΓΉ voti in una ListBox, calcola la media e mostra la valutazione finale (usa l'Esercizio 3 + la ListBox, che vedrai tra due lezioni)
π Teoria collegata (percorso C# β il linguaggio, esempi in console): Strutture di controllo e Gestione delle eccezioni.




