Vai al contenuto

Parco Auto 1: classi e oggetti

Dalle stringhe agli oggetti: la classe Automobile con campi privati e proprietΓ , una List di oggetti, aggiungere, modificare, eliminare e ordinare.

Il Grande Salto: Da Stringhe a Oggetti

Nella lezione su ListBox e ComboBox hai imparato a usare List<string> per gestire elenchi di dati. Ma c'Γ¨ un problema: le stringhe sono limitate!

❌ Il Problema delle Stringhe

Prima - Approccio con Stringhe

// Prodotto come stringa concatenata
string prodotto = "Laptop - 1200 - Elettronica - 5";
//                  ↑       ↑      ↑             ↑
//                 Nome  Prezzo  Categoria   QuantitΓ 

// 😱 PROBLEMI:
// 1. Difficile da modificare (devi separare con Split)
// 2. Errori di battitura (1200 o "1200"?)
// 3. Non puoi ordinare facilmente per prezzo
// 4. Nessun controllo sui dati (prezzo negativo?)

βœ… La Soluzione: Classi Personalizzate

Ora - Approccio con Oggetti

// Auto come OGGETTO con proprietΓ  definite
Automobile auto = new Automobile("Fiat 500", 1200, "Benzina");
auto.CambiaModello("Fiat Panda");    // Facile da modificare!
auto.CambiaPrezzo(15000);

// βœ… VANTAGGI:
// 1. ProprietΓ  chiare e protette
// 2. Validazione automatica dei dati
// 3. Ordinamento automatico per qualsiasi campo
// 4. Controllo completo sui valori

πŸ“š Cosa Imparerai in Questa Lezione

  • βœ… Creare Classi in Visual Studio: Procedura passo-passo
  • βœ… Campi Privati e ProprietΓ : Il metodo professionale completo
  • βœ… Costruttori: Inizializzare oggetti in modo sicuro
  • βœ… List<Automobile>: Liste di oggetti complessi
  • βœ… CRUD Completo: Create, Read, Update, Delete
  • βœ… Ordinamento Semplice: Ordinare liste facilmente
  • ⏭️ Nelle prossime due lezioni: salvare su file (TXT e CSV) ed ereditarietΓ 

Teoria: Le Classi in C#

Cos'Γ¨ una Classe?

Una classe è come un "modello" o "stampo" per creare oggetti. È un contenitore che raggruppa dati (proprietà) e comportamenti (metodi) correlati.

🎯 Analogia del Mondo Reale:

Immagina di voler costruire automobili in fabbrica:

  • CLASSE Automobile: Il progetto/disegno tecnico su carta (esiste 1 sola volta)
  • OGGETTO auto1: Una Fiat 500 rossa costruita dal progetto (reale, fisica)
  • OGGETTO auto2: Una Fiat 500 blu costruita dallo stesso progetto (diversa da auto1)
  • OGGETTO auto3: Un'altra Fiat 500 verde (sempre dal progetto)
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   CLASSE Automobile             β”‚  ← Il PROGETTO (su carta)
β”‚   - Modello                     β”‚     Esiste 1 sola volta
β”‚   - Cilindrata                  β”‚
β”‚   - Carburante                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
           β”‚
           β”‚ Crea oggetti da questo progetto
           ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ auto1        β”‚  β”‚ auto2        β”‚  β”‚ auto3        β”‚
β”‚ Fiat 500     β”‚  β”‚ Fiat 500     β”‚  β”‚ Fiat 500     β”‚
β”‚ 1200cc       β”‚  β”‚ 1200cc       β”‚  β”‚ 1200cc       β”‚
β”‚ Benzina      β”‚  β”‚ Diesel       β”‚  β”‚ GPL          β”‚
β”‚ ROSSA        β”‚  β”‚ BLU          β”‚  β”‚ VERDE        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
    ↑ OGGETTO       ↑ OGGETTO       ↑ OGGETTO
    Copia reale     Copia reale     Copia reale

Come Creare una Classe in Visual Studio

πŸ› οΈ Procedura Passo-Passo

STEP 1: Aprire Visual Studio e il Tuo Progetto

  1. Apri Visual Studio
  2. Apri il tuo progetto esistente (es: "ParcoAuto")

STEP 2: Aggiungere una Nuova Classe

  1. Guarda la finestra Esplora Soluzioni (Solution Explorer) sulla destra
  2. Fai clic destro sul nome del progetto "ParcoAuto"
  3. Nel menu che appare, seleziona: Aggiungi β†’ Nuovo elemento...
  4. Si aprirΓ  una finestra "Aggiungi nuovo elemento"
  5. Nella lista centrale, seleziona Classe (Class)
  6. In basso, nel campo Nome, scrivi: Automobile.cs
  7. Clicca Aggiungi

πŸ“Έ Visualizzazione Esplora Soluzioni:

Solution Explorer
└── πŸ“ ParcoAuto  ← CLIC DESTRO QUI!
    β”œβ”€β”€ πŸ“ Properties
    β”œβ”€β”€ πŸ“„ Form1.cs
    β”œβ”€β”€ πŸ“„ Form1.Designer.cs
    └── πŸ“„ Program.cs

Dopo "Aggiungi β†’ Nuovo elemento β†’ Classe":

Solution Explorer
└── πŸ“ ParcoAuto
    β”œβ”€β”€ πŸ“ Properties
    β”œβ”€β”€ πŸ“„ Automobile.cs  ← NUOVO FILE!
    β”œβ”€β”€ πŸ“„ Form1.cs
    β”œβ”€β”€ πŸ“„ Form1.Designer.cs
    └── πŸ“„ Program.cs

πŸ’‘ Nota Importante

Visual Studio creerΓ  automaticamente il file Automobile.cs con un template base. Lo modificheremo nei prossimi step per aggiungere le nostre proprietΓ !

Anatomia di una Classe - Metodo Professionale

Automobile.cs - La Classe Completa con Campi Privati

using System;

namespace ParcoAuto
{
    // ═══════════════════════════════════════════════
    // CLASSE: Modello per creare oggetti Automobile
    // ═══════════════════════════════════════════════
    public class Automobile
    {
        // ───────────────────────────────────────────
        // CAMPI PRIVATI: Dati nascosti all'esterno
        // ───────────────────────────────────────────
        // Il trattino basso _ indica che Γ¨ una variabile privata
        private string _modello;
        private int _cilindrata;
        private string _carburante;

        // ───────────────────────────────────────────
        // PROPRIETΓ€ PUBBLICHE: Accesso controllato ai dati
        // ───────────────────────────────────────────

        // ProprietΓ  Modello
        public string Modello
        {
            get
            {
                // Quando qualcuno LEGGE il valore
                return _modello;
            }
            set
            {
                // Quando qualcuno SCRIVE il valore
                // Posso fare controlli prima di salvare!
                if (!string.IsNullOrEmpty(value))
                {
                    _modello = value;
                }
            }
        }

        // ProprietΓ  Cilindrata
        public int Cilindrata
        {
            get
            {
                return _cilindrata;
            }
            set
            {
                // VALIDAZIONE: cilindrata deve essere ragionevole
                if (value >= 500 && value <= 10000)
                {
                    _cilindrata = value;
                }
                else
                {
                    // Se il valore non Γ¨ valido, non cambiare niente
                    // (o puoi mostrare un messaggio di errore)
                }
            }
        }

        // ProprietΓ  Carburante
        public string Carburante
        {
            get
            {
                return _carburante;
            }
            set
            {
                if (!string.IsNullOrEmpty(value))
                {
                    _carburante = value;
                }
            }
        }

        // ───────────────────────────────────────────
        // COSTRUTTORE: Crea l'auto con valori iniziali
        // ───────────────────────────────────────────
        public Automobile(string modello, int cilindrata, string carburante)
        {
            // Usa le proprietΓ  per avere la validazione automatica
            Modello = modello;
            Cilindrata = cilindrata;
            Carburante = carburante;
        }

        // ───────────────────────────────────────────
        // METODI: Comportamenti dell'auto
        // ───────────────────────────────────────────

        // Metodo per visualizzare l'auto formattata
        public string Stampa()
        {
            return $"{Modello} - {Cilindrata}cc - {Carburante}";
        }

        // Override ToString per visualizzazione automatica
        public override string ToString()
        {
            return Stampa();
        }
    }
}

PerchΓ© Serve ToString()? Spiegazione Fondamentale

πŸ“– Il Problema Senza ToString()

Quando aggiungi un oggetto alla ListBox, C# deve sapere COSA VISUALIZZARE. Se non gli dici nulla, mostrerΓ  una cosa bruttissima e inutile!

❌ SENZA ToString() - Risultato Brutto

public class Automobile
{
    // ... campi e proprietΓ  ...

    public string Stampa()
    {
        return $"{Modello} - {Cilindrata}cc - {Carburante}";
    }

    // ❌ NON c'è ToString()!
}

// Nel Form:
Automobile auto = new Automobile("Fiat 500", 1200, "Benzina");
lstAuto.Items.Add(auto);

// La ListBox mostra:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ ParcoAuto.Automobile        β”‚  ← Brutto! Solo il nome della classe!
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

βœ… CON ToString() - Risultato Perfetto

public class Automobile
{
    // ... campi e proprietΓ  ...

    public string Stampa()
    {
        return $"{Modello} - {Cilindrata}cc - {Carburante}";
    }

    // βœ… Override ToString()
    public override string ToString()
    {
        return Stampa();  // Chiama il metodo Stampa()
    }
}

// Nel Form:
Automobile auto = new Automobile("Fiat 500", 1200, "Benzina");
lstAuto.Items.Add(auto);

// La ListBox mostra:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Fiat 500 - 1200cc - Benzina β”‚  ← Perfetto! Dati leggibili!
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

🎬 Cosa Succede Dietro le Quinte

// Quando scrivi:
lstAuto.Items.Add(auto);

// C# fa AUTOMATICAMENTE questo:
lstAuto.Items.Add(auto.ToString());
//                     ↑
//                 Chiama ToString()!

// Se TU hai scritto ToString():
public override string ToString()
{
    return Stampa();  // Ritorna "Fiat 500 - 1200cc - Benzina"
}

// Se NON hai scritto ToString():
// C# usa quello di default che ritorna solo il nome della classe:
// "ParcoAuto.Automobile" ← INUTILE!

πŸ’‘ PerchΓ© "override"?

La parola override significa "sostituisco la versione vecchia con la mia".

// TUTTI gli oggetti in C# hanno giΓ  un ToString()
// che fa una cosa generica (mostra il nome della classe)

// Quando scrivi "override", dici a C#:
// "Ehi, quando qualcuno chiama ToString() sul MIO oggetto,
//  NON usare quello generico, usa il MIO!"

public override string ToString()  // ← "override" = sostituisci!
{
    return Stampa();  // La MIA versione personalizzata
}

πŸ€” PerchΓ© Non Usare Direttamente Stampa()?

Potresti pensare: "Perché non fare così ogni volta?"

// ❌ Opzione 1: Chiamare Stampa() manualmente (SCOMODO)
lstAuto.Items.Add(auto.Stampa());
// Funziona, ma devi ricordartelo OGNI volta!
// Se dimentichi, vedi "ParcoAuto.Automobile"

// βœ… Opzione 2: Override ToString() (AUTOMATICO)
lstAuto.Items.Add(auto);
// C# chiama ToString() automaticamente!
// PiΓΉ comodo, piΓΉ professionale, meno errori!

Con ToString(), il tuo oggetto "sa presentarsi da solo" in modo automatico!

πŸ“Š Confronto Visuale

Situazione Cosa Vedi Risultato
Senza ToString() ParcoAuto.Automobile ❌ Inutile
Con ToString() Fiat 500 - 1200cc - Benzina βœ… Perfetto!

🎯 In Parole Semplici

Senza ToString():

"Ehi ListBox, aggiungi questa auto!" ListBox: "Ok, ma cosa scrivo? Non lo so... scrivo 'ParcoAuto.Automobile'" πŸ˜•

Con ToString():

"Ehi ListBox, aggiungi questa auto!" ListBox: "Ok, la chiamo per sapere come presentarsi..." Auto: "Ciao! Io sono 'Fiat 500 - 1200cc - Benzina'!" 😊 ListBox: "Perfetto, scrivo questo!"

πŸ’‘ Regola Pratica da Ricordare

Ogni volta che crei una classe che verrΓ  visualizzata (in ListBox, ComboBox, MessageBox, ecc.), scrivi SEMPRE ToString() per dire come deve apparire!

// Schema da seguire SEMPRE:
public class MiaClasse
{
    // 1. Campi privati
    private string _dato1;
    private int _dato2;

    // 2. ProprietΓ  pubbliche
    public string Dato1
    {
        get { return _dato1; }
        set { _dato1 = value; }
    }

    // 3. Costruttore
    public MiaClasse(string dato1, int dato2)
    {
        Dato1 = dato1;
        Dato2 = dato2;
    }

    // 4. Metodo Stampa per formattare
    public string Stampa()
    {
        return $"{_dato1} - {_dato2}";
    }

    // 5. βœ… SEMPRE: Override ToString()
    public override string ToString()
    {
        return Stampa();
    }
}

πŸ§ͺ Dove Viene Usato ToString() Automaticamente?

ToString() viene chiamato automaticamente in MOLTE situazioni:

Automobile auto = new Automobile("Fiat 500", 1200, "Benzina");

// 1. Quando aggiungi a ListBox o ComboBox
lstAuto.Items.Add(auto);  // Chiama auto.ToString()

// 2. Quando concateni con una stringa
string messaggio = "Ho comprato: " + auto;
// auto viene convertito con ToString()
// Risultato: "Ho comprato: Fiat 500 - 1200cc - Benzina"

// 3. Quando usi in MessageBox
MessageBox.Show("Auto selezionata: " + auto);
// Chiama ToString()

// 4. Quando usi Console.WriteLine
Console.WriteLine(auto);  // Chiama ToString()

// In TUTTI questi casi, se non hai ToString(),
// vedresti solo "ParcoAuto.Automobile" ❌

PerchΓ© Usare Campi Privati + ProprietΓ ?

πŸ“– Spiegazione Semplice

Immagina di avere una cassaforte (campo privato _cilindrata) con una porta speciale (proprietΓ  Cilindrata). Quando qualcuno vuole mettere soldi nella cassaforte, la porta controlla se i soldi sono veri o falsi prima di accettarli!

🎯 Esempio Pratico:

// Qualcuno prova a impostare una cilindrata assurda:
auto.Cilindrata = -5000;  // Valore assurdo!

// Cosa succede dietro le quinte:
public int Cilindrata
{
    set
    {
        if (value >= 500 && value <= 10000)  // Controllo!
        {
            _cilindrata = value;  // OK, salvo
        }
        else
        {
            // RIFIUTO il valore! _cilindrata rimane com'era
        }
    }
}

// Risultato: il valore NON viene cambiato!
// La cassaforte ha rifiutato i "soldi falsi"!

βœ… I Vantaggi Spiegati Semplicemente:

  1. Protezione: Nessuno puΓ² mettere valori assurdi nei tuoi dati
  2. Controllo: Tu decidi cosa accettare e cosa rifiutare
  3. Sicurezza: Il campo privato (_cilindrata) Γ¨ nascosto, solo la proprietΓ  Γ¨ visibile
  4. FlessibilitΓ : Puoi cambiare come funziona internamente senza rompere il codice esistente

🎬 Come Funziona - Passo Passo:

// 1. Crei un'auto
Automobile auto = new Automobile("Fiat 500", 1200, "Benzina");

// 2. Provi a leggere la cilindrata
int valore = auto.Cilindrata;
//            ↓
// Chiama il GET:
// get { return _cilindrata; }  ← Ritorna 1200

// 3. Provi a cambiare la cilindrata
auto.Cilindrata = 2000;
//                ↓
// Chiama il SET:
// set
// {
//     if (2000 >= 500 && 2000 <= 10000) ← 2000 Γ¨ OK! // { // _cilindrata = 2000; ← Salva il nuovo valore // } // } // 4. Provi a mettere un valore assurdo auto.Cilindrata = -5000; // ↓ // Chiama il SET: // set // { // if (-5000 >= 500 && -5000 <= 10000)  ← -5000 NON Γ¨ OK!
//     {
//         // Non entra qui!
//     }
//     // _cilindrata rimane 2000, non cambia!
// }

πŸ”‘ Schema Visuale: Campo Privato + ProprietΓ 

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚              CLASSE AUTOMOBILE                  β”‚
β”‚                                                 β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”           β”‚
β”‚  β”‚ CAMPO PRIVATO (Cassaforte)      β”‚           β”‚
β”‚  β”‚ private int _cilindrata;        β”‚           β”‚
β”‚  β”‚ ← NASCOSTO dall'esterno         β”‚           β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜           β”‚
β”‚                   ↑                             β”‚
β”‚                   β”‚                             β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”‚
β”‚  β”‚ PROPRIETΓ€ PUBBLICA (Porta)        β”‚         β”‚
β”‚  β”‚ public int Cilindrata             β”‚         β”‚
β”‚  β”‚ {                                 β”‚         β”‚
β”‚  β”‚   get { return _cilindrata; }    │← LEGGI  β”‚
β”‚  β”‚   set { /* controlli */ }        │← SCRIVI β”‚
β”‚  β”‚ }                                 β”‚         β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                    ↑
                    β”‚
        Codice esterno accede SOLO alla proprietΓ 
        auto.Cilindrata = 1200;  βœ…
        auto._cilindrata = 1200; ❌ ERRORE! Privato!

Progetto Base: Parco Auto Semplice

Ora creiamo un'applicazione completa per gestire un parco automobili. Puoi aggiungere auto, visualizzarle e rimuoverle. Ogni auto Γ¨ un oggetto con proprietΓ  protette!

  1. Interfaccia Grafica
Tipo Controllo Name Scopo
TextBox txtModello Modello auto (es: "Fiat 500")
TextBox txtCilindrata Cilindrata in cc (es: "1200")
ComboBox cmbCarburante Tipo carburante (Benzina, Diesel, ecc.)
Button btnAggiungi Aggiungi auto alla lista
Button btnRimuovi Rimuovi auto selezionata
ListBox lstAuto Elenco auto nel parco
Label lblTotaleAuto Mostra quante auto ci sono
  1. Codice Completo Form - Spiegato Passo Passo

Form1.cs

using System;
using System.Collections.Generic;
using System.Windows.Forms;

namespace ParcoAuto
{
    public partial class Form1 : Form
    {
        // ═══════════════════════════════════════
        // VARIABILE GLOBALE: Lista di Automobile
        // ═══════════════════════════════════════
        // Questa lista contiene tutti gli oggetti Automobile
        private List<Automobile> listaAuto;

        public Form1()
        {
            InitializeComponent();

            // Crea una nuova lista vuota
            listaAuto = new List<Automobile>();

            // Riempi la ComboBox con i tipi di carburante
            InizializzaCarburanti();
        }

        // ═══════════════════════════════════════
        // Riempi la ComboBox con i carburanti
        // ═══════════════════════════════════════
        private void InizializzaCarburanti()
        {
            cmbCarburante.Items.Add("Scegli carburante");
            cmbCarburante.Items.Add("Benzina");
            cmbCarburante.Items.Add("Diesel");
            cmbCarburante.Items.Add("GPL");
            cmbCarburante.Items.Add("Metano");
            cmbCarburante.Items.Add("Elettrica");
            cmbCarburante.Items.Add("Ibrida");

            // Seleziona il primo elemento
            cmbCarburante.SelectedIndex = 0;
        }

        // ═══════════════════════════════════════
        // EVENTO: Aggiungi auto (clic su pulsante)
        // ═══════════════════════════════════════
        private void btnAggiungi_Click(object sender, EventArgs e)
        {
            // STEP 1: Controlla che tutti i campi siano compilati
            if (!ControllaCampi())
            {
                return;  // Esci dal metodo se i campi non sono OK
            }

            // STEP 2: Controlla che la cilindrata sia un numero valido
            if (!ValidaCilindrata(txtCilindrata.Text))
            {
                return;  // Esci se la cilindrata non Γ¨ valida
            }

            // STEP 3: Prendi i valori dalle TextBox
            string modello = txtModello.Text;
            int cilindrata = Convert.ToInt32(txtCilindrata.Text);
            string carburante = cmbCarburante.SelectedItem.ToString();

            // STEP 4: CREA UN NUOVO OGGETTO Automobile
            // Il costruttore riceve i 3 parametri
            Automobile nuovaAuto = new Automobile(modello, cilindrata, carburante);

            // STEP 5: Aggiungi l'oggetto alla lista
            listaAuto.Add(nuovaAuto);

            // STEP 6: Aggiorna quello che vedi sullo schermo
            AggiornaListaAuto();     // Aggiorna la ListBox
            AggiornaStatistiche();    // Aggiorna il contatore
            PulisciCampi();           // Pulisci le TextBox

            // STEP 7: Mostra messaggio di conferma
            MessageBox.Show("Auto aggiunta con successo!",
                          "Operazione Completata",
                          MessageBoxButtons.OK,
                          MessageBoxIcon.Information);
        }

        // ═══════════════════════════════════════
        // Controlla che i campi siano compilati
        // ═══════════════════════════════════════
        private bool ControllaCampi()
        {
            // Controlla modello
            if (string.IsNullOrEmpty(txtModello.Text))
            {
                MessageBox.Show("Devi inserire il modello dell'auto!",
                              "Campo Mancante",
                              MessageBoxButtons.OK,
                              MessageBoxIcon.Warning);
                return false;
            }

            // Controlla cilindrata
            if (string.IsNullOrEmpty(txtCilindrata.Text))
            {
                MessageBox.Show("Devi inserire la cilindrata!",
                              "Campo Mancante",
                              MessageBoxButtons.OK,
                              MessageBoxIcon.Warning);
                return false;
            }

            // Controlla carburante
            if (cmbCarburante.SelectedIndex == 0)
            {
                MessageBox.Show("Devi selezionare il tipo di carburante!",
                              "Campo Mancante",
                              MessageBoxButtons.OK,
                              MessageBoxIcon.Warning);
                return false;
            }

            // Se arrivo qui, tutti i campi sono OK
            return true;
        }

        // ═══════════════════════════════════════
        // Controlla che la cilindrata sia valida
        // ═══════════════════════════════════════
        private bool ValidaCilindrata(string testo)
        {
            try
            {
                // Prova a convertire il testo in numero
                int cilindrata = Convert.ToInt32(testo);

                // Controlla che sia in un range sensato
                if (cilindrata <= 0 || cilindrata > 10000)
                {
                    MessageBox.Show("La cilindrata deve essere tra 1 e 10000 cc!",
                                  "Valore Non Valido",
                                  MessageBoxButtons.OK,
                                  MessageBoxIcon.Warning);
                    return false;
                }

                return true;  // Il valore Γ¨ OK
            }
            catch
            {
                // Se la conversione fallisce (es: "abc" non Γ¨ un numero)
                MessageBox.Show("Devi inserire un numero valido per la cilindrata!",
                              "Errore",
                              MessageBoxButtons.OK,
                              MessageBoxIcon.Error);
                return false;
            }
        }
    }
}

PerchΓ© Validare Sia nel Form CHE nella Classe?

πŸ“– Domanda Importante: Non Basta Validare in UN Solo Posto?

Potresti pensare: "PerchΓ© fare i controlli due volte? Se controllo nel Form, basta quello!" Risposta: Sono DUE tipi di validazione con scopi DIVERSI!

🎯 I Due Livelli di Protezione

Tipo Dove Scopo Cosa Fa
Validazione FORM ControllaCampi() ValidaCilindrata() Aiutare l'UTENTE Messaggi chiari "Devi compilare questo campo!"
Validazione CLASSE ProprietΓ  SET Proteggere i DATI Rifiuta valori assurdi (silenzioso)

1️⃣ Validazione nel FORM - Per l'Esperienza Utente

// Nel Form - Controlli per l'UTENTE
private bool ControllaCampi()
{
    if (string.IsNullOrEmpty(txtModello.Text))
    {
        MessageBox.Show("⚠️ Devi inserire il modello!");
        txtModello.Focus();  // Porta il cursore sul campo
        return false;
    }
    return true;
}

// πŸ‘€ ESPERIENZA UTENTE:
// 1. L'utente lascia vuoto il campo modello
// 2. Clicca "Aggiungi"
// 3. Vede subito: "⚠️ Devi inserire il modello!"
// 4. Il cursore va automaticamente sul campo da compilare
// βœ… CHIARO E UTILE! L'utente capisce cosa fare!

2️⃣ Validazione nella CLASSE - Per la Sicurezza dei Dati

// Nella Classe - Protezione SEMPRE ATTIVA
public int Cilindrata
{
    set
    {
        if (value >= 500 && value <= 10000)
        {
            _cilindrata = value;  // OK, salva
        }
        else
        {
            // RIFIUTA valori assurdi (silenzioso)
            // NON salva niente
        }
    }
}

// πŸ›‘οΈ PROTEZIONE:
// Anche se qualcuno scrive PER ERRORE:
auto.Cilindrata = -9999;
// Il valore NON viene salvato!
// I dati rimangono SEMPRE validi! βœ…

🎬 Cosa Succederebbe SENZA Una delle Due?

// ════════════════════════════════════════════════════
// SCENARIO A: Solo validazione FORM (senza Classe)
// ════════════════════════════════════════════════════

// Il Form Γ¨ protetto βœ…
// MA in futuro potresti usare la classe altrove:

// Esempio: Carica dati da file
foreach (string riga in File.ReadAllLines("auto.txt"))
{
    string[] parti = riga.Split(';');
    Automobile auto = new Automobile();
    auto.Cilindrata = Convert.ToInt32(parti[1]);
    // ↑ Se il file Γ¨ corrotto e ha "-999"?
    // ❌ SENZA validazione nella classe: LO ACCETTA!
    // I dati diventano INVALIDI!
}

// ════════════════════════════════════════════════════
// SCENARIO B: Solo validazione CLASSE (senza Form)
// ════════════════════════════════════════════════════

private void btnAggiungi_Click(object sender, EventArgs e)
{
    // ❌ NO controlli nel Form!

    // Crea direttamente
    Automobile auto = new Automobile(
        txtModello.Text,           // Potrebbe essere VUOTO!
        Convert.ToInt32(txtCilindrata.Text),  // πŸ’₯ CRASH se vuoto!
        ...
    );
}

// πŸ’₯ PROBLEMA:
// - Se txtCilindrata Γ¨ vuoto β†’ CRASH! (Convert fallisce)
// - Se txtCilindrata = "abc" β†’ CRASH!
// - L'utente vede un errore incomprensibile
// ❌ PESSIMA esperienza utente!

// ════════════════════════════════════════════════════
// SCENARIO C: ENTRAMBI (CORRETTO!)
// ════════════════════════════════════════════════════

// Nel Form: messaggi chiari per l'utente βœ…
// Nella Classe: protezione sempre attiva βœ…

// βœ… RISULTATO:
// 1. L'utente riceve aiuto chiaro
// 2. I dati sono SEMPRE protetti
// 3. La classe Γ¨ sicura ovunque la usi

πŸ’‘ Analogia Semplice: La Banca

🏦 Validazione FORM = Sportello con l'impiegato

L'impiegato ti aiuta gentilmente: "Scusi, manca la sua firma qui." "Questo modulo non Γ¨ compilato correttamente." β†’ Ti GUIDA a fare le cose bene

πŸ”’ Validazione CLASSE = Cassaforte automatica

Anche se l'impiegato sbaglia e prova a mettere soldi falsi, la cassaforte ha un sensore che li RIFIUTA automaticamente. Non si fida SOLO dell'impiegato!

βœ… Servono ENTRAMBI:

  • L'impiegato (Form) aiuta il cliente
  • La cassaforte (Classe) protegge i soldi SEMPRE

🎯 Quando Usi la Classe SENZA il Form?

Ci sono tanti casi in cui usi gli oggetti SENZA passare dal Form:

// Caso 1: Caricamento da file
List<Automobile> lista = new List<Automobile>();
foreach (string riga in File.ReadAllLines("auto.txt"))
{
    // ... parsing della riga ...
    auto.Cilindrata = valore;  // ← La classe PROTEGGE qui!
}

// Caso 2: Modifica diretta (senza Form)
Automobile auto = listaAuto[indice];
auto.Cilindrata = nuovoValore;  // ← La classe PROTEGGE qui!

// Caso 3: Dati da internet/database
Automobile auto = new Automobile();
auto.Cilindrata = datiDalServer.Cil;  // ← La classe PROTEGGE qui!

// In TUTTI questi casi NON c'Γ¨ il Form!
// Ma i dati sono COMUNQUE protetti dalla validazione nella classe! βœ…

πŸ’‘ Regola Pratica Finale

Dove Cosa Controllare Come Reagire
FORM β€’ Campi vuoti β€’ Formato corretto β€’ Input utente valido MessageBox chiaro Focus sul campo return (esci)
CLASSE β€’ Valori assurdi β€’ Limiti logici β€’ Coerenza dati Rifiuta silenziosamente NON salvare (mantieni valore precedente)

🎯 Conclusione: ENTRAMBI = Programmazione PROFESSIONALE!

  • Form: Migliora l'esperienza utente (messaggi chiari e utili)
  • Classe: Protegge i dati da QUALSIASI fonte (Form, file, rete, altro codice)
  • Insieme: App robusta, sicura e user-friendly!

Form1.cs (continua...)

        // ═══════════════════════════════════════
        // Aggiorna la ListBox con tutte le auto
        // ═══════════════════════════════════════
        private void AggiornaListaAuto()
        {
            // STEP 1: Pulisci la ListBox
            lstAuto.Items.Clear();

            // STEP 2: Aggiungi ogni auto dalla lista
            foreach (Automobile auto in listaAuto)
            {
                // Quando aggiungi un oggetto Automobile,
                // la ListBox chiama automaticamente il metodo ToString()
                // che ritorna: "Fiat 500 - 1200cc - Benzina"
                lstAuto.Items.Add(auto);
            }
        }

        // ═══════════════════════════════════════
        // Aggiorna il contatore delle auto
        // ═══════════════════════════════════════
        private void AggiornaStatistiche()
        {
            // Conta quante auto ci sono nella lista
            int numeroAuto = listaAuto.Count;

            // Mostra il numero nella Label
            lblTotaleAuto.Text = $"Totale auto nel parco: {numeroAuto}";
        }

        // ═══════════════════════════════════════
        // Pulisci tutti i campi del form
        // ═══════════════════════════════════════
        private void PulisciCampi()
        {
            txtModello.Text = "";
            txtCilindrata.Text = "";
            cmbCarburante.SelectedIndex = 0;

            // Metti il cursore sul primo campo
            txtModello.Focus();
        }

        // ═══════════════════════════════════════
        // EVENTO: Rimuovi auto (clic su pulsante)
        // ═══════════════════════════════════════
        private void btnRimuovi_Click(object sender, EventArgs e)
        {
            // Controlla se hai selezionato un'auto
            if (lstAuto.SelectedIndex == -1)
            {
                MessageBox.Show("Devi selezionare un'auto da rimuovere!",
                              "Nessuna Selezione",
                              MessageBoxButtons.OK,
                              MessageBoxIcon.Warning);
                return;
            }

            // Prendi l'auto selezionata dalla lista
            Automobile autoSelezionata = listaAuto[lstAuto.SelectedIndex];

            // Salva il modello per il messaggio
            string modello = autoSelezionata.Modello;

            // Rimuovi l'auto dalla lista
            listaAuto.RemoveAt(lstAuto.SelectedIndex);

            // Aggiorna la visualizzazione
            AggiornaListaAuto();
            AggiornaStatistiche();

            // Mostra messaggio di conferma
            MessageBox.Show($"L'auto '{modello}' Γ¨ stata rimossa!",
                          "Auto Rimossa",
                          MessageBoxButtons.OK,
                          MessageBoxIcon.Information);
        }
    }
}

FunzionalitΓ  MODIFICA - Spiegazione Completa

🎯 Come Funziona la Modifica?

Per modificare un'auto esistente, usiamo una variabile di stato che ci dice se siamo in "modalitΓ  aggiungi" o "modalitΓ  modifica". Il bello Γ¨ che NON serve un pulsante separato: lo stesso pulsante "Aggiungi" cambia funzione automaticamente!

πŸ’‘ UN SOLO PULSANTE per Due Funzioni!

Non ti serve aggiungere un pulsante "Modifica" separato! Il pulsante "Aggiungi" Γ¨ intelligente:

  • πŸ“ Normalmente: Si chiama "Aggiungi" e aggiunge nuove auto
  • ✏️ Quando selezioni un'auto: Cambia in "Salva Modifiche" e modifica l'auto selezionata
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ ModalitΓ  NORMALE (Aggiungi)       β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ [Modello]  [_____________]         β”‚
β”‚ [Cilindrata] [___________]         β”‚
β”‚                                    β”‚
β”‚ [ Aggiungi ] ← Pulsante NORMALE   β”‚
β”‚                                    β”‚
β”‚ ListBox:                           β”‚
β”‚   BMW Serie 3                      β”‚
β”‚   Tesla Model 3                    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

        ↓ CLICCHI su "BMW Serie 3"

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ ModalitΓ  MODIFICA                  β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ [Modello]  [_BMW Serie 3___]       β”‚
β”‚ [Cilindrata] [__2000_______]       β”‚
β”‚                                    β”‚
β”‚ [ βœ… Salva Modifiche ] ← CAMBIATO!β”‚
β”‚    (Arancione)                     β”‚
β”‚                                    β”‚
β”‚ ListBox:                           β”‚
β”‚   BMW Serie 3 ← Selezionata       β”‚
β”‚   Tesla Model 3                    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
  1. NON Serve Aggiungere Altri Pulsanti!

Usa solo i pulsanti che hai giΓ :

  • βœ… btnAggiungi β†’ Fa sia "Aggiungi" che "Modifica"
  • βœ… btnRimuovi β†’ Rimuove l'auto selezionata
  • βž• btnAnnulla (OPZIONALE) β†’ Annulla la modifica e torna in modalitΓ  Aggiungi
  1. Codice Completo per la Modifica - Spiegato Passo Passo

Form1.cs - FunzionalitΓ  Modifica con UN SOLO Pulsante

public partial class Form1 : Form
{
    private List<Automobile> listaAuto;

    // ═══════════════════════════════════════
    // VARIABILE DI STATO: Controlla la modalitΓ 
    // ═══════════════════════════════════════
    // -1 = modalitΓ  AGGIUNGI (default)
    // Altro numero = modalitΓ  MODIFICA (indice dell'auto da modificare)
    private int indiceModifica = -1;

    // ... altri metodi ...

    // ═══════════════════════════════════════
    // EVENTO: Quando CLICCHI su un'auto nella ListBox
    // ═══════════════════════════════════════
    // Questo evento si attiva AUTOMATICAMENTE quando selezioni un'auto!
    private void lstAuto_SelectedIndexChanged(object sender, EventArgs e)
    {
        // STEP 1: Controlla se hai davvero selezionato qualcosa
        if (lstAuto.SelectedIndex == -1)
        {
            return;  // Niente selezionato, esci
        }

        // STEP 2: Prendi l'auto selezionata dalla lista
        // lstAuto.SelectedIndex ti dice QUALE riga hai cliccato (0, 1, 2, ecc.)
        Automobile autoSelezionata = listaAuto[lstAuto.SelectedIndex];

        // STEP 3: Riempi i campi del form con i dati dell'auto
        // In questo modo l'utente puΓ² vedere e modificare i valori
        txtModello.Text = autoSelezionata.Modello;
        txtCilindrata.Text = autoSelezionata.Cilindrata.ToString();
        cmbCarburante.SelectedItem = autoSelezionata.Carburante;

        // STEP 4: Salva l'indice dell'auto che stai modificando
        indiceModifica = lstAuto.SelectedIndex;

        // STEP 5: CAMBIA IL PULSANTE per indicare la modalitΓ  MODIFICA
        btnAggiungi.Text = "βœ… Salva Modifiche";
        btnAggiungi.BackColor = Color.Orange;  // Colore diverso per attirare l'attenzione

        MessageBox.Show("Ora puoi modificare i dati e cliccare 'Salva Modifiche'",
                      "ModalitΓ  Modifica Attivata",
                      MessageBoxButtons.OK,
                      MessageBoxIcon.Information);
    }

    // ═══════════════════════════════════════
    // EVENTO: Aggiungi O Modifica (in base alla modalitΓ )
    // ═══════════════════════════════════════
    // Questo Γ¨ lo STESSO pulsante di prima!
    // MA ora Γ¨ "intelligente" e sa cosa fare!
    private void btnAggiungi_Click(object sender, EventArgs e)
    {
        // STEP 1: Validazione (sempre necessaria!)
        if (!ControllaCampi() || !ValidaCilindrata(txtCilindrata.Text))
        {
            return;
        }

        // STEP 2: Raccogli i dati dai campi
        string modello = txtModello.Text;
        int cilindrata = Convert.ToInt32(txtCilindrata.Text);
        string carburante = cmbCarburante.SelectedItem.ToString();

        // STEP 3: Crea un nuovo oggetto Automobile
        Automobile auto = new Automobile(modello, cilindrata, carburante);

        // STEP 4: Controlla la modalitΓ  e decidi cosa fare
        if (indiceModifica == -1)
        {
            // ═══════════════════════════════════
            // MODALITΓ€ AGGIUNGI (normale)
            // ═══════════════════════════════════
            listaAuto.Add(auto);

            MessageBox.Show("Auto aggiunta con successo!",
                          "Operazione Completata",
                          MessageBoxButtons.OK,
                          MessageBoxIcon.Information);
        }
        else
        {
            // ═══════════════════════════════════
            // MODALITΓ€ MODIFICA
            // ═══════════════════════════════════
            // Sostituisci l'auto vecchia con quella nuova
            listaAuto[indiceModifica] = auto;

            // IMPORTANTE: Torna in modalitΓ  AGGIUNGI
            indiceModifica = -1;
            btnAggiungi.Text = "Aggiungi";
            btnAggiungi.BackColor = SystemColors.Control;  // Colore normale

            MessageBox.Show("Auto modificata con successo!",
                          "Modifica Completata",
                          MessageBoxButtons.OK,
                          MessageBoxIcon.Information);
        }

        // STEP 5: Aggiorna visualizzazione e pulisci campi
        AggiornaListaAuto();
        AggiornaStatistiche();
        PulisciCampi();
    }

    // ═══════════════════════════════════════
    // PULSANTE ANNULLA (Opzionale ma consigliato!)
    // ═══════════════════════════════════════
    // Aggiungi questo pulsante solo SE vuoi dare all'utente
    // la possibilitΓ  di annullare una modifica
    private void btnAnnulla_Click(object sender, EventArgs e)
    {
        // Torna in modalitΓ  AGGIUNGI senza salvare modifiche
        indiceModifica = -1;
        btnAggiungi.Text = "Aggiungi";
        btnAggiungi.BackColor = SystemColors.Control;

        PulisciCampi();

        MessageBox.Show("Modifica annullata",
                      "Annullato",
                      MessageBoxButtons.OK,
                      MessageBoxIcon.Information);
    }

    // ... altri metodi ...
}
  1. Come Funziona - Spiegazione Visuale
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ SCENARIO 1: AGGIUNGI (indiceModifica = -1)         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

1. Utente compila i campi
   txtModello: "Fiat 500"
   txtCilindrata: "1200"

2. Clicca "Aggiungi"

3. Controllo:
   if (indiceModifica == -1)  ← TRUE!
   {
       listaAuto.Add(auto);  ← AGGIUNGI alla fine
   }

4. Lista DOPO:
   [0] BMW Serie 3
   [1] Tesla Model 3
   [2] Fiat 500  ← NUOVA AUTO aggiunta!

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ SCENARIO 2: MODIFICA (indiceModifica = 0)          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

1. Utente CLICCA su "BMW Serie 3" nella ListBox
   β†’ lstAuto_SelectedIndexChanged viene chiamato

2. Il metodo fa:
   autoSelezionata = listaAuto[0];  ← Prendi BMW
   txtModello.Text = "BMW Serie 3";  ← Riempi i campi
   txtCilindrata.Text = "2000";

   indiceModifica = 0;  ← Salva l'indice!
   btnAggiungi.Text = "βœ… Salva Modifiche";

3. Utente MODIFICA i campi:
   txtModello: "BMW Serie 5"  ← CAMBIATO!
   txtCilindrata: "3000"      ← CAMBIATO!

4. Utente clicca "Salva Modifiche"

5. Controllo:
   if (indiceModifica == -1)  ← FALSE!
   else  ← Entra qui!
   {
       listaAuto[0] = auto;  ← SOSTITUISCI all'indice 0
   }

6. Lista DOPO:
   [0] BMW Serie 5 - 3000cc  ← AUTO MODIFICATA!
   [1] Tesla Model 3
   [2] Fiat 500

7. Torna in modalitΓ  AGGIUNGI:
   indiceModifica = -1;
   btnAggiungi.Text = "Aggiungi";

πŸ”‘ Concetti Chiave

1️⃣ Variabile di Stato: indiceModifica

private int indiceModifica = -1;

// -1 = ModalitΓ  AGGIUNGI (nessuna modifica in corso)
// 0, 1, 2, ecc. = ModalitΓ  MODIFICA (modifica l'auto a quell'indice)

// Esempio:
if (indiceModifica == -1)
{
    // AGGIUNGI: crea una nuova auto
    listaAuto.Add(auto);
}
else
{
    // MODIFICA: sostituisci l'auto esistente
    listaAuto[indiceModifica] = auto;
}

2️⃣ Evento SelectedIndexChanged

// Si attiva quando l'utente CLICCA su un elemento della ListBox
private void lstAuto_SelectedIndexChanged(object sender, EventArgs e)
{
    // lstAuto.SelectedIndex = quale riga hai cliccato (0, 1, 2, ...)
    // -1 = niente selezionato

    if (lstAuto.SelectedIndex != -1)
    {
        Automobile auto = listaAuto[lstAuto.SelectedIndex];
        // Ora hai l'auto selezionata!
    }
}

3️⃣ Riempire i Campi dal l'Oggetto

// Prendi i dati dall'oggetto e mettili nelle TextBox
txtModello.Text = auto.Modello;           // String β†’ TextBox
txtCilindrata.Text = auto.Cilindrata.ToString();  // int β†’ string β†’ TextBox
cmbCarburante.SelectedItem = auto.Carburante;     // String β†’ ComboBox

4️⃣ Sostituire l'Elemento nella Lista

// SBAGLIATO - Modifica solo in memoria locale:
Automobile temp = listaAuto[0];
temp.Modello = "Nuovo";  // Questo FUNZIONA, ma Γ¨ confuso

// CORRETTO - Crea un nuovo oggetto e sostituisci:
Automobile nuovaAuto = new Automobile("Nuovo", 1500, "GPL");
listaAuto[0] = nuovaAuto;  // Sostituisci completamente l'auto

πŸ’‘ Interfaccia Utente Migliorata

Per rendere chiaro all'utente in che modalitΓ  si trova:

// ModalitΓ  AGGIUNGI
btnAggiungi.Text = "Aggiungi";
btnAggiungi.BackColor = SystemColors.Control;  // Grigio normale
lblStato.Text = "ModalitΓ : Aggiungi nuova auto";

// ModalitΓ  MODIFICA
btnAggiungi.Text = "βœ… Salva Modifiche";
btnAggiungi.BackColor = Color.Orange;  // Arancione per attirare attenzione
lblStato.Text = $"ModalitΓ : Modifica auto '{auto.Modello}'";

⚠️ Errori Comuni da Evitare

❌ Errore 1: Dimenticare di resettare indiceModifica

// SBAGLIATO:
if (indiceModifica != -1)
{
    listaAuto[indiceModifica] = auto;
    // ❌ Dimenticato: indiceModifica = -1;
}

// Problema: rimane in modalitΓ  modifica!
// Il prossimo clic su "Aggiungi" modificherΓ  di nuovo!

❌ Errore 2: Non controllare SelectedIndex prima di usarlo

// SBAGLIATO:
private void lstAuto_SelectedIndexChanged(object sender, EventArgs e)
{
    Automobile auto = listaAuto[lstAuto.SelectedIndex];
    // ❌ Se SelectedIndex = -1, CRASH!
}

// CORRETTO:
private void lstAuto_SelectedIndexChanged(object sender, EventArgs e)
{
    if (lstAuto.SelectedIndex == -1)
        return;  // βœ… Controlla sempre!

    Automobile auto = listaAuto[lstAuto.SelectedIndex];
}

βœ… Soluzione: Usa sempre questo pattern

// PATTERN SICURO per la modifica:

// 1. All'inizio del form:
private int indiceModifica = -1;

// 2. Quando selezioni:
private void lstAuto_SelectedIndexChanged(...)
{
    if (lstAuto.SelectedIndex == -1) return;
    // ... codice ...
    indiceModifica = lstAuto.SelectedIndex;
    btnAggiungi.Text = "Salva Modifiche";
}

// 3. Quando salvi:
private void btnAggiungi_Click(...)
{
    // ... validazione ...

    if (indiceModifica == -1)
    {
        listaAuto.Add(auto);
    }
    else
    {
        listaAuto[indiceModifica] = auto;
        indiceModifica = -1;  // βœ… RESET!
        btnAggiungi.Text = "Aggiungi";
    }

    AggiornaListaAuto();
}

Cosa Succede Quando Aggiungi un'Auto - Passo Passo

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ STEP 1: Utente riempie i campi                  β”‚
β”‚ txtModello: "Fiat 500"                           β”‚
β”‚ txtCilindrata: "1200"                            β”‚
β”‚ cmbCarburante: "Benzina"                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                    ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ STEP 2: Utente clicca "Aggiungi"                β”‚
β”‚ β†’ Il metodo btnAggiungi_Click viene eseguito    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                    ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ STEP 3: Controlli di validazione                β”‚
β”‚ βœ… Modello compilato                            β”‚
β”‚ βœ… Cilindrata compilata                         β”‚
β”‚ βœ… Cilindrata Γ¨ un numero (1200)                β”‚
β”‚ βœ… Cilindrata tra 1 e 10000                     β”‚
β”‚ βœ… Carburante selezionato                       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                    ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ STEP 4: Crea l'oggetto Automobile               β”‚
β”‚                                                  β”‚
β”‚ new Automobile("Fiat 500", 1200, "Benzina")     β”‚
β”‚                                                  β”‚
β”‚ Il COSTRUTTORE fa:                              β”‚
β”‚ Modello = "Fiat 500"                            β”‚
β”‚ ↓ chiama il SET della proprietΓ  Modello        β”‚
β”‚ ↓ controlla che non sia vuoto                  β”‚
β”‚ ↓ salva in _modello                            β”‚
β”‚                                                  β”‚
β”‚ Cilindrata = 1200                               β”‚
β”‚ ↓ chiama il SET della proprietΓ  Cilindrata     β”‚
β”‚ ↓ controlla che sia tra 500 e 10000            β”‚
β”‚ ↓ salva in _cilindrata                         β”‚
β”‚                                                  β”‚
β”‚ Carburante = "Benzina"                          β”‚
β”‚ ↓ chiama il SET della proprietΓ  Carburante     β”‚
β”‚ ↓ controlla che non sia vuoto                  β”‚
β”‚ ↓ salva in _carburante                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                    ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ STEP 5: Oggetto creato e pronto!                β”‚
β”‚                                                  β”‚
β”‚ nuovaAuto = {                                   β”‚
β”‚     _modello: "Fiat 500",                       β”‚
β”‚     _cilindrata: 1200,                          β”‚
β”‚     _carburante: "Benzina"                      β”‚
β”‚ }                                               β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                    ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ STEP 6: Aggiungi alla lista                     β”‚
β”‚ listaAuto.Add(nuovaAuto)                         β”‚
β”‚                                                  β”‚
β”‚ La lista ora contiene:                          β”‚
β”‚ [0] β†’ Automobile {Fiat 500, 1200, Benzina}      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                    ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ STEP 7: Aggiorna la ListBox                     β”‚
β”‚ lstAuto.Items.Add(nuovaAuto)                     β”‚
β”‚                                                  β”‚
β”‚ Internamente chiama: nuovaAuto.ToString()       β”‚
β”‚ Che ritorna: "Fiat 500 - 1200cc - Benzina"     β”‚
β”‚                                                  β”‚
β”‚ La ListBox mostra:                              β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”               β”‚
β”‚ β”‚ Fiat 500 - 1200cc - Benzina  β”‚               β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜               β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸš— Il Progetto Parco Auto Γ¨ diviso in tre lezioni: in questa costruisci la classe e il gestionale, nella seconda salvi e carichi i dati su file, nella terza aggiungi ereditarietΓ  e polimorfismo. Tieni da parte il progetto: lo riprenderai nelle prossime due.

Ordinare le Auto - Metodo Semplice

Vuoi vedere le auto in ordine alfabetico o per cilindrata? Ecco come fare in modo semplice!

  1. Aggiungi un Pulsante per Ordinare
  • Trascina un Button nel form
  • Chiamalo btnOrdina
  • Imposta la proprietΓ  Text su "Ordina per Modello"
  1. Codice per Ordinare

Ordinamento Alfabetico

// ═══════════════════════════════════════
// EVENTO: Ordina le auto per modello
// ═══════════════════════════════════════
private void btnOrdina_Click(object sender, EventArgs e)
{
    // Controlla se ci sono auto da ordinare
    if (listaAuto.Count == 0)
    {
        MessageBox.Show("Non ci sono auto da ordinare!",
                      "Lista Vuota",
                      MessageBoxButtons.OK,
                      MessageBoxIcon.Information);
        return;
    }

    // Ordina la lista in ordine alfabetico per modello
    // Sort() usa il metodo CompareTo per confrontare le stringhe
    listaAuto.Sort((auto1, auto2) => auto1.Modello.CompareTo(auto2.Modello));

    // Aggiorna la visualizzazione
    AggiornaListaAuto();

    // Mostra messaggio
    MessageBox.Show("Auto ordinate per modello in ordine alfabetico!",
                  "Ordinamento Completato",
                  MessageBoxButtons.OK,
                  MessageBoxIcon.Information);
}

πŸ” Spiegazione del Codice di Ordinamento

Cosa fa questa riga?

listaAuto.Sort((auto1, auto2) => auto1.Modello.CompareTo(auto2.Modello));

È più semplice di quanto sembri! Funziona così:

  1. Sort() prende le auto due alla volta
  2. Confronta i loro modelli con CompareTo
  3. Se auto1 viene prima di auto2 alfabeticamente, le lascia in quest'ordine
  4. Altrimenti le scambia
  5. Ripete fino a quando tutte le auto sono in ordine

πŸ’‘ Esempio Visuale:

PRIMA dell'ordinamento:
[0] Tesla Model 3
[1] Fiat 500
[2] BMW Serie 3

DOPO l'ordinamento:
[0] BMW Serie 3      ← Viene prima alfabeticamente
[1] Fiat 500
[2] Tesla Model 3

🎯 Vuoi Ordinare per Cilindrata?

Cambia semplicemente la riga così:

// Ordina per cilindrata (dal piΓΉ piccolo al piΓΉ grande)
listaAuto.Sort((auto1, auto2) => auto1.Cilindrata.CompareTo(auto2.Cilindrata));

Riepilogo: Cosa Hai Imparato

1️⃣ Classi con Campi Privati

Il metodo professionale: private _campo + proprietΓ  pubblica con validazione. I dati dell'oggetto sono protetti!

2️⃣ Liste di Oggetti

Da List<string> a List<Automobile>: ogni elemento della lista Γ¨ un oggetto con le sue proprietΓ .

3️⃣ Operazioni CRUD

Create (aggiungi), Read (visualizza), Update (modifica), Delete (rimuovi): le operazioni base di ogni gestionale.

4️⃣ Validazione e Ordinamento

Controlli sui valori inseriti, sia nel form sia nella classe, e liste ordinate con Sort().

Esercizi per Fare Pratica

1️⃣ Gestionale Contatti

  • Crea una classe Contatto con: Nome, Cognome, Telefono, Email
  • Usa campi privati con proprietΓ 
  • Aggiungi validazione: email deve contenere @, telefono solo numeri
  • Permetti di ordinare per cognome

2️⃣ Registro Voti

  • Crea una classe Studente con: Nome, Materia, Voto
  • Il voto deve essere tra 0 e 10 (validazione nel SET)
  • Calcola e mostra la media dei voti
  • Trova lo studente con il voto piΓΉ alto

3️⃣ Catalogo Libri

  • Crea una classe Libro con: Titolo, Autore, Anno, Prezzo
  • Aggiungi un metodo che calcola l'etΓ  del libro
  • Permetti di cercare libri per autore
  • Ordina per prezzo (dal piΓΉ economico al piΓΉ costoso)

πŸ’Ύ Conserva questi progetti: nella prossima lezione aggiungerai il salvataggio su file.

πŸ“š Teoria collegata (percorso C# – il linguaggio, esempi in console): Programmazione a oggetti: i fondamenti.