Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
A kivételek azt jelzik, hogy hiba történt a program futtatása során. Kivételobjektumok, amelyek hibát írnak le, létre vannak hozva és aztán a throw utasítással vagy kifejezéssel. A futtatókörnyezet ezután megkeresi a legkompatibilisebb kivételkezelőt.
A programozóknak kivételeket kell kivenniük, ha az alábbi feltételek közül legalább egy teljesül:
A metódus nem tudja befejezni a definiált funkcióit. Ha például egy metódus paraméterének értéke érvénytelen:
static void CopyObject(SampleClass original) { _ = original ?? throw new ArgumentException("Parameter cannot be null", nameof(original)); }Az objektum állapota alapján nem megfelelő hívás történik egy objektumra. Ilyen lehet például egy írásvédett fájlba való írás. Azokban az esetekben, amikor egy objektum állapota nem teszi lehetővé a műveletet, dobjon egy példányt a InvalidOperationException vagy egy olyan objektumot, amely ezen osztály származékán alapul. Az alábbi kód egy példa egy olyan metódusra, amely egy InvalidOperationException objektumot dob:
public class ProgramLog { FileStream logFile = null!; public void OpenLog(FileInfo fileName, FileMode mode) { } public void WriteLog() { if (!logFile.CanWrite) { throw new InvalidOperationException("Logfile cannot be read-only"); } // Else write data to the log and return. } }Ha egy metódus argumentuma kivételt okoz. Ebben az esetben az eredeti kivételt kell észlelni, majd létrehozni egy ArgumentException példányt. Az eredeti kivételt a ArgumentException konstruktorának kell átadni InnerException paraméterként:
static int GetValueFromArray(int[] array, int index) { try { return array[index]; } catch (IndexOutOfRangeException e) { throw new ArgumentOutOfRangeException( "Parameter index is out of range.", e); } }Jegyzet
Az előző példa a
InnerExceptiontulajdonság használatát mutatja be. Szándékosan leegyszerűsítik. A gyakorlatban a használat előtt ellenőriznie kell, hogy egy index tartományon belül van-e. Ezt a technikát akkor használhatja kivétel körbefuttatására, ha egy paraméter egy tagja olyan kivételt ad ki, amely nem várható a tag meghívása előtt.
A kivételek egy StackTracenevű tulajdonságot tartalmaznak. Ez a karakterlánc tartalmazza az aktuális hívásverem metódusainak nevét, a fájlnevet és a sorszámot, ahol a kivétel keletkezett az egyes metódusok esetében. A StackTrace objektumot a közös nyelvi futtatókörnyezet (CLR) automatikusan hozza létre a throw utasítás pontjáról, így a kivételeket attól a ponttól kell elvetni, ahol a veremkövetésnek el kell kezdődnie.
Minden kivétel tartalmaz egy Messagenevű tulajdonságot. Ezt a sztringet úgy kell beállítani, hogy elmagyarázza a kivétel okát. A biztonságra érzékeny információkat nem szabad az üzenet szövegébe helyezni. A Messagemellett ArgumentException egy ParamName nevű tulajdonságot is tartalmaz, amelyet a kivételt okozó argumentum nevére kell beállítani. Egy tulajdonságbeállítóban a ParamName értékét value-re kell állítani.
A nyilvános és védett metódusok kivételeket vetnek fel, ha nem tudják elvégezni a kívánt függvényeiket. A kidobott kivételosztály a rendelkezésre álló legspecifikusabb kivétel, amely megfelel a hibafeltételeknek. Ezeket a kivételeket az osztályfunkció részeként kell dokumentálni, és az eredeti osztály származtatott osztályainak vagy frissítéseinek ugyanazt a viselkedést kell megőrizniük a visszamenőleges kompatibilitás érdekében.
A kivételek eldobásakor megfontolandó szempontok
Az alábbi lista a kivételek kivetésekor megfontolandó eljárásokat azonosítja:
- Ne használjon kivételeket egy program folyamatának módosításához a szokásos végrehajtás részeként. Használjon kivételeket a hibafeltételek jelentéséhez és kezeléséhez.
- A kivételeket nem szabad visszatérési értékként vagy paraméterként visszaadni ahelyett, hogy kidobták volna őket.
- Ne dobjon szándékosan System.Exception, System.SystemException, System.NullReferenceExceptionvagy System.IndexOutOfRangeException a saját forráskódjából.
- Ne hozzon létre kivételeket, amelyek hibakeresési módban, de kiadási módban nem hozhatók létre. A fejlesztési fázisban előforduló futásidejű hibák azonosításához használja inkább a Debug Assert eszközt.
Kivételek a feladatokat visszaadó metódusokban
A async módosítóval deklarált metódusoknak különleges szempontokat kell figyelembe venniük a kivételek tekintetében. A async metódusban szereplő kivételek a visszaadott tevékenységben vannak tárolva, és csak akkor jelennek meg, ha például a tevékenységre várni kell. A tárolt kivételekről további információt Aszinkron kivételekcímű témakörben talál.
Javasoljuk, hogy a metódusok aszinkron részeinek megadása előtt ellenőrizze az argumentumokat, és adjon meg minden megfelelő kivételt, például ArgumentException és ArgumentNullException. Vagyis ezeknek az érvényesítési kivételeknek szinkron módon kell megjelenniük a munka megkezdése előtt. A következő kódrészlet egy példát mutat be, ahol, ha kivételek dobódnak, a ArgumentException kivételek szinkron módon jelennek meg, míg a InvalidOperationException a visszaadott feladatba lesz tárolva.
// Non-async, task-returning method.
// Within this method (but outside of the local function),
// any thrown exceptions emerge synchronously.
public static Task<Toast> ToastBreadAsync(int slices, int toastTime)
{
if (slices is < 1 or > 4)
{
throw new ArgumentException(
"You must specify between 1 and 4 slices of bread.",
nameof(slices));
}
if (toastTime < 1)
{
throw new ArgumentException(
"Toast time is too short.", nameof(toastTime));
}
return ToastBreadAsyncCore(slices, toastTime);
// Local async function.
// Within this function, any thrown exceptions are stored in the task.
static async Task<Toast> ToastBreadAsyncCore(int slices, int time)
{
for (int slice = 0; slice < slices; slice++)
{
Console.WriteLine("Putting a slice of bread in the toaster");
}
// Start toasting.
await Task.Delay(time);
if (time > 2_000)
{
throw new InvalidOperationException("The toaster is on fire!");
}
Console.WriteLine("Toast is ready!");
return new Toast();
}
}
Kivételosztályok definiálása
A programok előre definiált kivételosztályt állíthatnak be a System névtérbe (kivéve, ha korábban feljegyezték), vagy létrehozhatják saját kivételosztályaikat a Exceptionalapján. A származtatott osztályoknak legalább három konstruktort kell meghatározniuk: egy paraméter nélküli konstruktort, egy olyant, amely beállítja az üzenettulajdonságot, valamint egyet, amely a Message és a InnerException tulajdonságokat is beállítja. Például:
[Serializable]
public class InvalidDepartmentException : Exception
{
public InvalidDepartmentException() : base() { }
public InvalidDepartmentException(string message) : base(message) { }
public InvalidDepartmentException(string message, Exception inner) : base(message, inner) { }
}
Új tulajdonságok hozzáadása a kivételosztályhoz, ha az általuk megadott adatok hasznosak a kivétel feloldásához. Ha új tulajdonságokat ad hozzá a származtatott kivételosztályhoz, ToString()-t felül kell írni a hozzáadott adatok visszaadásához.
C# nyelvspecifikáció
További információkért lásd: Kivételek és A dob utasítás a C# nyelvi specifikációban. A nyelvi specifikáció a C#-szintaxis és -használat végleges forrása.