Grafikus C# – Windows Forms tanfolyam › 13.4 lecke Windows Forms · 13.4 lecke · kivételkezelés A kivételkezelés alapjait a 4. fejezetben már megismerted. Most tudatosan használjuk: mikor érdemes elkapni a kivételt, és mikor kell inkább megelőzni; hogyan működik több try, catch és finally
catch blokk és a finally; mit jelent a throw és a throw ex közötti különbség; hogyan készítesz saját kivételtípust; és hogyan állítasz be végső védőhálót a Program.cs-ben, hogy a program soha ne omoljon össze kezeletlen kivétel ablakkal. A cél a hibatűrő program: amikor valami elromlik, a felhasználó érthető üzenetet kap, az adatai nem vesznek el, és a fejlesztő a naplóból megtudja, mi történt.
A lecke végére
- helyesen használsz több
catchblokkot (specifikustól az általánosig) és kivételszűrőt (when); - a
finallyblokkban takarítasz (kurzor, gombok, fájl, kapcsolat), és érted, mikor fut le; - eldöntöd, hogy a hibát megelőzöd (ellenőrzés,
TryParse) vagy elkapod; - különbséget teszel a
throw;és athrow ex;között, és beágyazod az eredeti kivételt (InnerException); - saját kivételtípust írsz;
- globális hibakezelőt állítasz be (
Application.ThreadException,AppDomain.UnhandledException) és naplózol.
Mielőtt elkezded
Ehhez a leckéhez a 4.7 lecke (kivételkezelés alapjai), a 13.1–13.3 lecke és a 10.9 lecke (mentési hibák) szükséges.
A try–catch–finally szerkezete
private void btnBeolvas_Click(object sender, EventArgs e)
{
btnBeolvas.Enabled = false;
this.Cursor = Cursors.WaitCursor;
try
{
string tartalom = File.ReadAllText(txtUt.Text);
int szam = int.Parse(tartalom.Trim());
lblEredmeny.Text = (100 / szam).ToString();
}
catch (FileNotFoundException) // 1. a LEGSPECIFIKUSABB elöl
{
lblEredmeny.Text = "A fájl nem található.";
}
catch (FormatException)
{
lblEredmeny.Text = "A fájl nem számot tartalmaz.";
}
catch (DivideByZeroException)
{
lblEredmeny.Text = "Nullával nem lehet osztani.";
}
catch (IOException ex) when (ex.HResult == unchecked((int)0x80070020)) // kivételszűrő: csak ezt az esetet (fájlzár)
{
lblEredmeny.Text = "A fájlt másik program használja.";
}
catch (IOException ex) // 2. az általánosabb IOException UTÁN
{
lblEredmeny.Text = "Olvasási hiba: " + ex.Message;
}
finally
{
this.Cursor = Cursors.Default; // MINDIG lefut: siker, hiba, vagy return esetén is
btnBeolvas.Enabled = true;
}
}catch-hez kerül. Ezért a specifikus típus előre, az általános hátra: a FileNotFoundException az IOException leszármazottja, ezért előbb kell állnia. Fordítva a fordító hibát ad (CS0160: egy korábbi catch már elkapja).catch (...) when (feltétel) csak akkor kapja el a kivételt, ha a feltétel igaz; különben továbbmegy a következő catch-hez. Így ugyanazon típust a részletei szerint különválaszthatod, és a stack trace érintetlen marad.finally blokk lefut, ha a try sikeresen befejeződik, ha kivétel keletkezik (elkapva vagy nem), és ha a try-ban return áll. Ott takarítasz: kurzor, gombok, megnyitott fájl vagy kapcsolat. A using utasítás valójában try–finally.Environment.Exit, Environment.FailFast, áramszünet, a folyamat erőszakos leállítása), vagy végtelen ciklus/holtpont van a try-ban. Egyébként mindig.Jósolj!
A try blokkban return; áll, a finally-ban pedig btnBeolvas.Enabled = true;. Lefut-e a finally?
Jóslat ellenőrzése
Igen: a finally a return előtt lefut (a metódus csak utána lép ki). Ezért ideális a gombok visszaengedésére: nem maradhat tiltva a gomb, bármi történik.
Elkapni vagy megelőzni?
| Kivétel | Eredet | Mit tegyél? |
|---|---|---|
FormatException, OverflowException (szám-szövegből) | A felhasználó hibás bevitele: várható. | Előzd meg: int.TryParse, nincs kivétel. |
NullReferenceException, IndexOutOfRangeException, ArgumentNullException | Programozói hiba. | Javítsd a kódot (ellenőrzés, helyes index), ne kapd el. |
DivideByZeroException | Hiányzó ellenőrzés (programozói hiba). | if (n != 0) ellenőrzés; csak végszükségben elkapni. |
FileNotFoundException, IOException, UnauthorizedAccessException | Környezeti hiba: a program nem befolyásolhatja (lemez, jog, zárolás). | Kapd el, jelezd, tegyél valamit (újrapróbálás, másik hely). |
HttpRequestException, TimeoutException, adatbázis-hiba | Külső rendszer hibája. | Kapd el, és kezeld (újrapróbálás, offline mód). |
InvalidOperationException, KeyNotFoundException | Rossz állapot vagy hiányzó kulcs. | Előzd meg (TryGetValue, állapot-ellenőrzés), vagy kapd el, ha az állapot külső. |
// ROSSZ: a várható hibát kivétellel kezeljük (lassú, zajos, nehezen olvasható)
try { szam = int.Parse(txtSzam.Text); }
catch (FormatException) { lblHiba.Text = "Számot adj meg!"; return; }
// JÓ: a várható hibát ellenőrzéssel kezeljük
int szam;
if (!int.TryParse(txtSzam.Text, out szam)) { lblHiba.Text = "Számot adj meg!"; return; }
// A környezeti hiba KIVÉTEL (nem lehet előre biztosan tudni): ott try–catch
try { File.WriteAllText(ut, szoveg); }
catch (UnauthorizedAccessException) { lblHiba.Text = "Nincs jogosultság a mentéshez."; }
catch (IOException ex) { lblHiba.Text = "A mentés nem sikerült: " + ex.Message; }
// A rossz minta: minden elnyelése
try { Mindent(); } catch { } // ✗✗✗ a hiba eltűnik, semmit sem tudsz róla
try { Mindent(); } catch (Exception) { } // ✗ ugyanazcatch { } a legrosszabb: a hiba „eltűnik”, a program tovább fut hibás állapotban, és a hibakeresés lehetetlen (13.3 lecke). Legalább naplózz.catch (Exception) mindent elkap, a programozói hibákat is (NullReferenceException), és elfedi őket. Fogd a konkrét típusokat. Széles catch csak a legfelső szinten (globális kezelő) indokolt.Jósolj!
Egy ciklus 10 000 felhasználói beírást dolgoz fel int.Parse + catch (FormatException) módszerrel, és a bemenetek fele hibás. Mi a gond az int.TryParse-hoz képest?
Jóslat ellenőrzése
A kivétel drága (a keletkezése és a stack trace összeállítása ezerszer lassabb lehet a sima összehasonlításnál): 5000 kivétel érezhetően lassít. Ráadásul a hibakeresőben „Break When Thrown” mellett minden hibás beírás megállítja a programot. A TryParse kivétel nélkül jelzi a hibát.
Dobás, továbbdobás, saját kivétel
// SAJÁT KIVÉTEL: a név megmondja, mi a baj; plusz adat a hibáról
public class ErvenytelenBevitelException : Exception
{
public string Mezo { get; private set; }
public ErvenytelenBevitelException(string mezo, string uzenet) : base(uzenet) { Mezo = mezo; }
public ErvenytelenBevitelException(string mezo, string uzenet, Exception ok) : base(uzenet, ok) { Mezo = mezo; }
}
// DOBÁS: ha a metódus nem tudja teljesíteni a feladatát, kivételt dob (nem ad vissza hibakódot)
public static int Kor(string szoveg)
{
int kor;
if (!int.TryParse(szoveg, out kor)) { throw new ErvenytelenBevitelException("kor", "Az életkor egész szám kell legyen."); }
if (kor < 0 || kor > 150) { throw new ErvenytelenBevitelException("kor", "Az életkor 0 és 150 között lehet."); }
return kor;
}
// TOVÁBBDOBÁS: naplózol, de a hívó is értesüljön
try { Mentes(); }
catch (IOException ex)
{
Naploz(ex);
throw; // ✓ az eredeti kivétel és stack trace megmarad
// throw ex; // ✗ a stack trace ELVÉSZ: a hiba helyének nyoma eltűnik
}
// BEÁGYAZÁS: más típusú kivétellé alakítod, de az eredeti az InnerException-ben marad
try { json = JsonSerializer.Deserialize<Beallitas>(szoveg); }
catch (JsonException ex)
{
throw new TaroloHiba("A beállításfájl sérült.", ex); // ex az InnerException
}throw; (változó nélkül) ugyanazt a kivételt dobja tovább, eredeti stack trace-szel. A throw ex; mintha újra dobnád: a stack trace az újradobás helyéről indul, az eredeti hely elvész. Mindig throw;.JsonException → TaroloHiba), az eredetit add át második paraméterként (InnerException): a naplóban látszik a valódi ok, a hívó pedig a saját rétegének típusát kapja (12.8 lecke).ErvenytelenBevitelException: jelöld a mezőt; TaroloHiba: mentési hiba üzenet). Névvége: Exception; az Exception-ből (nem ApplicationException-ből) származtasd.bool TrySomething(out ...) minta a várható hibákhoz való (TryParse), ahol a hiba a normális működés része.Jósolj!
A catch (Exception ex) { Naploz(ex); throw ex; } kódot használod egy mély metódusban. A naplóban a stack trace első sora a catch blokk sora, nem a hiba valódi helye. Miért?
Jóslat ellenőrzése
A throw ex; újraindítja a stack trace-t az adott soron: az eredeti hely elvész. A throw; megőrzi. A hibakeresés szempontjából a különbség óriási: a valódi hely nélkül órákig keresheted a hibát.
Globális hibakezelő: a végső védőháló
static class Program
{
[STAThread]
static void Main()
{
// a felületi szál kezeletlen kivételei ide futnak (nem omlik össze a program a hibaablakkal)
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
Application.ThreadException += (s, e) => Vegzetes(e.Exception);
// más szálak kezeletlen kivételei (ezeket már nem lehet megállítani, csak naplózni)
AppDomain.CurrentDomain.UnhandledException += (s, e) => Naploz(e.ExceptionObject as Exception);
Application.EnableVisualStyles();
Application.Run(new Form1());
}
private static void Vegzetes(Exception ex)
{
Naploz(ex); // 1. a részletek a naplóba (a fejlesztőnek)
DialogResult v = MessageBox.Show( // 2. érthető üzenet a felhasználónak, stack trace nélkül
"Váratlan hiba történt. A részleteket naplóba írtuk. Folytatod a használatot?",
"Hiba", MessageBoxButtons.YesNo, MessageBoxIcon.Error);
if (v == DialogResult.No) { Application.Exit(); } // 3. a felhasználó dönt; nem biztos, hogy biztonságos folytatni
}
private static void Naploz(Exception ex)
{
try
{
string mappa = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "MiProgram");
Directory.CreateDirectory(mappa);
File.AppendAllText(Path.Combine(mappa, "hiba.log"), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " " + ex + Environment.NewLine + Environment.NewLine); // ex.ToString(): típus, üzenet, stack trace, inner
}
catch { /* a naplózás hibája ne okozzon újabb hibát */ }
}
}UnhandledExceptionMode.CatchException beállítás biztosítja, hogy ide kerüljön (a konfigurációtól függetlenül).Thread, Task.Run nem várt kivétele, 11. fejezet). Itt már nem lehet megállítani az összeomlást, csak naplózni. Ezért kell a háttérmunkában try–catch.Jósolj!
A Naploz metódus a lemezre ír, a lemez tele van, és a naplózás maga is kivételt dob. Mi történik, ha a Naploz belsejében nincs try–catch?
Jóslat ellenőrzése
A hibakezelő hibázik: újabb kezeletlen kivétel keletkezik, amely a kezelőt újra hívhatja, vagy a program összeomlik. Az egyetlen hely, ahol az „elnyelő” catch indokolt: a naplózó belsejében, hogy a védőháló ne szakadjon el.
Mit tegyél ide: a hibatűrő átváltó: egy kezelt hiba üzenete és a globális hibaablak a naplózott hibával.Javasolt fájlnév: winforms-13-4-hibatures.webp · Alt szöveg: A hibatűrő átváltó program
Hibakeresés: te vagy a hibadetektív
Mi a baj, és hogyan javítod?
Gondold végig az okot, és csak utána nyisd le a megoldást.
1. CS0160: egy korábbi catch már elkapja
catch (IOException) { }
catch (FileNotFoundException) { } // sosem érhető elHiba és javítás
A leszármazott típus (FileNotFoundException) az általános (IOException) elé kerüljön.
2. A program nem jelez semmit
try { Mentes(); } catch { }Hiba és javítás
A hiba elnyelődik. Kapd el a konkrét kivételt, jelezz a felhasználónak, naplózz; ha nem tudsz mit tenni, ne kapd el.
3. A gomb tiltva marad
btnMent.Enabled = false;
try { Mentes(); btnMent.Enabled = true; }
catch (IOException) { lblHiba.Text = "Hiba"; }Hiba és javítás
Hibánál a Enabled = true sor kimarad. A takarítás a finally-ba való.
4. A stack trace elveszik
catch (Exception ex) { Naploz(ex); throw ex; }Hiba és javítás
throw; kell, mert a throw ex; újraindítja a stack trace-t.
5. A felhasználó stack trace-t lát
catch (Exception ex) { MessageBox.Show(ex.ToString()); }Hiba és javítás
A felhasználónak érthető üzenet kell, a részletek a naplóba mennek. A hosszú technikai szöveg ijesztő és használhatatlan.
6. Kivétel a ciklusban, mindig megáll
Egy 1000 elemes feldolgozásban egy hibás elem leállítja az egészet. A Ok és javítás
try–catch a ciklus körül áll, nem benne. Tedd az elemenkénti feldolgozás köré, így a hibás elemet kihagyod és naplózod, a többi lefut.
Mini projekt: hibatűrő átváltó
Készíts egységátváltó programot, amelyet nem lehet „összeomlasztani”: minden hibás bemenetre és környezeti hibára érthető választ ad, és a váratlan hibákat naplózza:
- Felület:
cmbMuvelet(Hőmérséklet °C→°F, Távolság km→mérföld, Arány (osztás), Fájlból olvasás),txtBemenet,txtMasodik(osztáshoz),txtUt(fájlhoz), Számol, Mentés naplóba;lblEredmeny,lblHiba; állapotsor;lstNaplo. - Saját kivétel:
ErvenytelenBevitelException(aMezotulajdonsággal); aBeolvassegédmetódus a hibás szöveget ezzel jelzi (TryParse, nemParse). - Logika: az átváltások külön statikus osztályban (12.7 lecke): a szükséges ellenőrzések (osztó ≠ 0, tartomány: hőmérséklet ≥ −273,15 °C)
ErvenytelenBevitelExceptionvagyArgumentOutOfRangeExceptionkivételt dobnak. - Specifikus catch-ek: a Számol kezelője külön ágon kezeli az
ErvenytelenBevitelException(a hibás mezőt jelöli azErrorProvider), aFileNotFoundException, azUnauthorizedAccessExceptionés azIOExceptioneseteit (whenszűrővel a fájlzárat: A fájlt másik program használja). - finally: a Számol gomb tiltása és a várakozó kurzor visszaállítása mindig a
finally-ban. - Továbbdobás és beágyazás: a fájlolvasó metódus a
FormatException-tErvenytelenBevitelException-né alakítja (az eredeti azInnerException); egy másik pontonthrow;naplózás után. - Globális kezelő: a
Program.cs-benThreadExceptionésUnhandledExceptionkezelő, napló a%AppData%mappába; egy rejtett Összeomlás-teszt gomb szándékosanInvalidOperationException-t dob (ellenőrzéshez). - Naplónézet: a Mentés naplóba a legutóbbi kezelt hibákat a
lstNaplolistában mutatja (a naplózó metódus belsejében védettcatch). - Teszteld: hibás szám, üres mező, 0 osztó, −300 °C, nem létező fájl, olvasásvédett fájl, megnyitott (zárolt) fájl, szöveges fájl számot várva, az Összeomlás-teszt, és ellenőrizd, hogy a gombok minden esetben visszaállnak.
Megoldás megnyitása (próbáld ki előbb önállóan!)
public class ErvenytelenBevitelException : Exception
{
public string Mezo { get; private set; }
public ErvenytelenBevitelException(string mezo, string uzenet) : base(uzenet) { Mezo = mezo; }
public ErvenytelenBevitelException(string mezo, string uzenet, Exception ok) : base(uzenet, ok) { Mezo = mezo; }
}
public static class Atvalto
{
public static double Beolvas(string szoveg, string mezo)
{
double d;
if (!double.TryParse((szoveg ?? "").Trim(), out d)) { throw new ErvenytelenBevitelException(mezo, "A(z) " + mezo + " mezőbe számot írj."); }
return d;
}
public static double CelsiusFahrenheit(double c)
{
if (c < -273.15) { throw new ErvenytelenBevitelException("hőmérséklet", "Az abszolút nulla (−273,15 °C) alatt nincs hőmérséklet."); }
return c * 9 / 5 + 32;
}
public static double KmMerfold(double km)
{
if (km < 0) { throw new ErvenytelenBevitelException("távolság", "A távolság nem lehet negatív."); }
return km * 0.621371;
}
public static double Oszt(double a, double b)
{
if (b == 0) { throw new ErvenytelenBevitelException("osztó", "Nullával nem lehet osztani."); }
return a / b;
}
public static double FajlbolSzam(string ut)
{
string tartalom = File.ReadAllText(ut);
try { return double.Parse(tartalom.Trim()); }
catch (FormatException ex) { throw new ErvenytelenBevitelException("fájl", "A fájl nem számot tartalmaz.", ex); } // beágyazás: az eredeti az InnerException
}
}
// ---- Form1.cs ----
private readonly List<string> kezeltHibak = new List<string>();
private void btnSzamol_Click(object sender, EventArgs e)
{
btnSzamol.Enabled = false;
Cursor = Cursors.WaitCursor;
errorProvider1.Clear();
lblHiba.Text = "";
try
{
switch (cmbMuvelet.SelectedIndex)
{
case 0: lblEredmeny.Text = Atvalto.CelsiusFahrenheit(Atvalto.Beolvas(txtBemenet.Text, "hőmérséklet")).ToString("0.##") + " °F"; break;
case 1: lblEredmeny.Text = Atvalto.KmMerfold(Atvalto.Beolvas(txtBemenet.Text, "távolság")).ToString("0.##") + " mérföld"; break;
case 2: lblEredmeny.Text = Atvalto.Oszt(Atvalto.Beolvas(txtBemenet.Text, "osztandó"), Atvalto.Beolvas(txtMasodik.Text, "osztó")).ToString("0.####"); break;
case 3: lblEredmeny.Text = Atvalto.FajlbolSzam(txtUt.Text).ToString("0.##"); break;
default: lblHiba.Text = "Válassz műveletet."; break;
}
}
catch (ErvenytelenBevitelException ex)
{
lblEredmeny.Text = "";
lblHiba.Text = ex.Message;
errorProvider1.SetError(ex.Mezo == "osztó" ? txtMasodik : ex.Mezo == "fájl" ? (Control)txtUt : txtBemenet, ex.Message);
Naploz("Érvénytelen bevitel (" + ex.Mezo + "): " + ex.Message);
}
catch (FileNotFoundException) { lblHiba.Text = "A fájl nem található."; Naploz("Fájl nem található: " + txtUt.Text); }
catch (DirectoryNotFoundException) { lblHiba.Text = "A mappa nem található."; Naploz("Mappa nem található: " + txtUt.Text); }
catch (UnauthorizedAccessException) { lblHiba.Text = "Nincs jogosultság a fájlhoz."; Naploz("Jogosultsághiba: " + txtUt.Text); }
catch (IOException ex) when ((ex.HResult & 0xFFFF) == 32 || (ex.HResult & 0xFFFF) == 33) // 32/33: a fájlt másik folyamat használja / zárolta
{
lblHiba.Text = "A fájlt másik program használja. Zárd be, és próbáld újra.";
Naploz("Fájlzár: " + txtUt.Text);
}
catch (IOException ex) { lblHiba.Text = "Olvasási hiba: " + ex.Message; Naploz(ex.ToString()); }
finally
{
Cursor = Cursors.Default; // mindig
btnSzamol.Enabled = true;
}
}
private void Naploz(string s)
{
kezeltHibak.Insert(0, DateTime.Now.ToString("HH:mm:ss") + " " + s);
lstNaplo.Items.Clear();
lstNaplo.Items.AddRange(kezeltHibak.Take(50).ToArray());
}
private void btnOsszeomlas_Click(object sender, EventArgs e)
{
throw new InvalidOperationException("Szándékos teszthiba a globális kezelő kipróbálásához.");
}Mit tegyél ide: a kész hibatűrő átváltó több kezelt hibával és a naplóval.Javasolt fájlnév: winforms-13-4-kesz.webp · Alt szöveg: A kész hibatűrő átváltó
Három önálló gyakorlófeladat
Egyszerre csak egyet csinálj: tervezd meg, írd meg, futtasd, ellenőrizd, és csak utána nyisd ki a megoldást.
1. Elemenkénti hibakezelés
Egy 500 soros szövegfájlt dolgozol fel soronként; néhány sor hibás. Hogyan haladsz tovább a hibás soroknál? A Egy lehetséges megoldás
try–catch a ciklus testében áll (soronként): a hibás sort naplózod (sorszám, ok), és továbblépsz; a végén összegzed: 480 sor feldolgozva, 20 hibás (lásd a naplót).
2. Újrapróbálás
Egy hálózati letöltés időnként Ciklus 1–3, HttpRequestException-t dob. Írj háromszori újrapróbálást növekvő várakozással.Egy lehetséges megoldás
try { ...; return; } catch (HttpRequestException) when (proba < 3) { await Task.Delay(proba * 1000); }; a harmadik hibánál a kivétel felfelé szál (a when már nem teljesül).
3. Végső hibaablak
Készíts egyedi hibaablakot a globális kezelőhöz: üzenet, Részletek (összecsukható), Napló megnyitása. Külön Egy lehetséges megoldás
HibaForm (ShowDialog), a kivétel szövege (ex.ToString()) egy összecsukható TextBoxban; a Napló megnyitása a Process.Start-tal a mappát nyitja (a felhasználónak nem kell keresnie).
Gyakorlótár: 6 további feladat
Három szinten gyakorolhatsz: alap, közepes és kihívás. Csak a próbálkozás után nyisd le a megoldást.
Alap szint
1. Sorrend
Milyen sorrendben írod a Előbb a catch (Exception) és a catch (FormatException) blokkot?Megoldás megnyitása
FormatException, utána az Exception: a specifikus típus elöl, az általános hátul.
2. Mikor fut a finally?
Fut-e, ha a Igen: a try-ban kivétel van, és nincs hozzá catch?Megoldás megnyitása
finally lefut, mielőtt a kivétel továbbhalad a hívóhoz.
Közepes szint
3. Megelőzni vagy elkapni?
Melyik: (a) üres lista első elemének olvasása; (b) hálózati fájl megnyitása? (a) megelőzni (Megoldás megnyitása
if (lista.Count > 0)); (b) elkapni (környezeti hiba, nem előre tudható).
4. throw vagy throw ex?
Miért Megőrzi az eredeti stack trace-t; a throw;?Megoldás megnyitása
throw ex; újraindítja a hívási lánc nyomát.
Kihívás szint
5. Kivétel a finally-ban
Mi történik, ha a Az új kivétel felülírja az eredetit (az eredeti elveszik). Ezért a finally blokk is kivételt dob?Megoldás megnyitása
finally legyen egyszerű és biztonságos; a kockázatos takarítást védd külön try–catch-csel.
6. Háttérszál
Miért nem fogja el a A kivétel a másik szálon keletkezik, a hívási lánca nem a try–catch a new Thread(...) belsejében dobott kivételt, ha a try a szálindítás körül áll?Megoldás megnyitása
try alatt fut. A try–catch a szál belsejébe (a munka köré) kell; a Task-nál az await hozza vissza a kivételt a hívóhoz (11.5 lecke).
Gyors önellenőrzés
Válaszolj fejben, és csak utána nyisd le a választ. Takarításra: mindig lefut (siker, hiba, return esetén is). A leggyakoribb/legspecifikusabb elöl, az általános hátul. Ha programozói hiba (null, index) vagy nincs mit tenni vele: javítsd a kódot, vagy hagyd felszállni. A Az eredeti kivételt hordozza, ha új típusúvá alakítod. A kezeletlen kivételek végső védőhálója ( Érthető üzenetet; a technikai részletek a naplóba mennek.1. Mire való a finally?
2. Hogyan sorrendezed a catch blokkokat?
3. Mikor ne kapd el a kivételt?
4. Mi a throw; és a throw ex; különbsége?
throw; megőrzi a stack trace-t, a throw ex; újraindítja.5. Mire jó az InnerException?
6. Mi a globális hibakezelő?
ThreadException, UnhandledException): naplóz és érthetően jelez.7. Mit mutatsz a felhasználónak?
Mit tudsz már?
- Több catch-et és kivételszűrőt használsz, és a finally-ban takarítasz.
- Eldöntöd, mikor előzöd meg a hibát, és mikor kapod el.
throw;és beágyazás segítségével megőrzöd az eredeti hibát; saját kivételtípust írsz.- Globális hibakezelőt állítasz be, és naplózol.
Következő lecke: Üres, hibás és szélsőértékes bevitelek
A felhasználói bevitel ellenőrzése: üres mezők, hibás formátum, határértékek, és érthető visszajelzés (ErrorProvider, Validating).


