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 C#-programozók egy próbablokkot használnak a kivétel által érintett kód particionálására. A kapcsolódó fogási blokkok az esetlegesen keletkező kivételek kezelésére szolgálnak. A végül blokkok olyan kódot tartalmaznak, amely akkor fut, ha kivétel van a try blokkban, például felszabadítja a try blokkban lefoglalt erőforrásokat. A try blokkokhoz egy vagy több társított catch blokk, blokk finally vagy mindkettő szükséges.
Az alábbi példák bemutatnak egy try-catch, egy try-finally és egy try-catch-finally utasítást.
try
{
// Code to try goes here.
}
catch (SomeSpecificException ex)
{
// Code to handle the exception goes here.
// Only catch exceptions that you know how to handle.
// Never catch base class System.Exception without
// rethrowing it at the end of the catch block.
}
try
{
// Code to try goes here.
}
finally
{
// Code to execute after the try block goes here.
}
try
{
// Code to try goes here.
}
catch (SomeSpecificException ex)
{
// Code to handle the exception goes here.
}
finally
{
// Code to execute after the try (and possibly catch) blocks
// goes here.
}
Egy `try` blokk `catch` vagy `finally` blokk nélkül fordítóhibát okoz.
Fogási blokkok
A catch blokk megadhatja, milyen típusú kivételt kell elkapni. A típusspecifikációt kivételszűrőnek nevezzük. A kivételtípust a következőből Exceptionkell származtatnia: . Általában ne határozzon meg Exception kivételszűrőt, hacsak nem tudja kezelni a try blokkban dobható összes kivételt, vagy ha a blokk végén tartalmaz egy throw
Több catch blokk különböző kivételosztályokkal összekapcsolható. A catch blokkok kiértékelése felülről lefelé történik a kódban, de minden egyes kidobott kivételhez csak egy catch blokk lesz végrehajtva. A rendszer végrehajtja az első catch blokkot, amely megadja a kidobott kivétel pontos típusát vagy alaposztályát. Ha egyetlen catch blokk sem ad meg egyező kivételosztályt, egy catch típussal nem rendelkező blokk kerül kiválasztásra, ha szerepel az utasításban. Fontos, hogy a catch blokkokat először a legspecifikusabb (vagyis a leginkább levezetett) kivételosztályokkal helyezze el.
Kivételeket észlel, ha a következő feltételek teljesülnek:
- Tisztában van azzal, hogy miért fordulhat elő kivétel, és implementálhat egy adott helyreállítást, például megkérheti a felhasználót, hogy adjon meg egy új fájlnevet egy FileNotFoundException objektum elfogásakor.
- Létrehozhat és elvethet egy új, pontosabb kivételt.
int GetInt(int[] array, int index) { try { return array[index]; } catch (IndexOutOfRangeException e) { throw new ArgumentOutOfRangeException( "Parameter index is out of range.", e); } } - Először csak részben szeretné kezelni a kivételt, mielőtt továbbadja további feldolgozásra. Az alábbi példában egy
catchblokk használatával adhat hozzá bejegyzést egy hibanaplóhoz a kivétel újbóli létrehozása előtt.try { // Try to access a resource. } catch (UnauthorizedAccessException e) { // Call a custom error logging procedure. LogError(e); // Re-throw the error. throw; }
Kivételszűrőket is megadhat, ha logikai kifejezést szeretne hozzáadni egy fogási záradékhoz. A kivételszűrők azt jelzik, hogy egy adott catch blokk csak akkor egyezik, ha a feltétel igaz. Az alábbi példában mindkét fogási záradék ugyanazt a kivételosztályt használja, de a rendszer egy további feltételt is bejelöl egy másik hibaüzenet létrehozásához:
int GetInt(int[] array, int index)
{
try
{
return array[index];
}
catch (IndexOutOfRangeException e) when (index < 0)
{
throw new ArgumentOutOfRangeException(
"Parameter index cannot be negative.", e);
}
catch (IndexOutOfRangeException e)
{
throw new ArgumentOutOfRangeException(
"Parameter index cannot be greater than the array size.", e);
}
}
A mindig visszaadott false kivételszűrővel megvizsgálhatja az összes kivételt, de nem dolgozhatja fel őket. Általában a kivételek naplózása használatos:
public class ExceptionFilter
{
public static void Main()
{
try
{
string? s = null;
Console.WriteLine(s.Length);
}
catch (Exception e) when (LogException(e))
{
}
Console.WriteLine("Exception must have been handled");
}
private static bool LogException(Exception e)
{
Console.WriteLine($"\tIn the log routine. Caught {e.GetType()}");
Console.WriteLine($"\tMessage: {e.Message}");
return false;
}
}
A LogException metódus mindig visszaadja a false értéket, mivel nincs catch záradék, ami illeszkedne ehhez a kivételszűrőhöz. A catch klauzula lehet általános System.Exception, és a későbbi klauzulák feldolgozhatnak pontosabb kivétel osztályokat.
Végül blokkok
A finally blokk lehetővé teszi a try blokkban végrehajtott műveletek rendbetételét. Ha jelen van, a finally blokk utoljára hajtódik végre, a try blokk és bármely egyező catch blokk után. A finally blokkok mindig futnak, függetlenül attól, hogy a rendszer kivételt ad ki, vagy a catch kivételtípusnak megfelelő blokk található.
A finally blokk olyan erőforrások kiadására használható, mint a fájlstreamek, az adatbázis-kapcsolatok és a grafikus leírók anélkül, hogy a futásidőben a szemétgyűjtőre várna az objektumok véglegesítéséhez.
Az alábbi példában a finally blokk a blokkban try megnyitott fájl bezárására szolgál. Figyelje meg, hogy a fájlleíró állapota a fájl bezárása előtt van ellenőrizve. Ha a try blokk nem tudja megnyitni a fájlt, a fájlkezelő továbbra is rendelkezik az értékkel null , és a finally blokk nem próbálja bezárni. Ehelyett, ha a fájl sikeresen meg van nyitva a try blokkban, a finally blokk bezárja a megnyitott fájlt.
FileStream? file = null;
FileInfo fileinfo = new System.IO.FileInfo("./file.txt");
try
{
file = fileinfo.OpenWrite();
file.WriteByte(0xF);
}
finally
{
// Check for null because OpenWrite might have failed.
file?.Close();
}
C# nyelvi specifikáció
További információkért tekintse meg a Kivételek és a The try utasítást a C# nyelvi specifikációjában. A nyelvi specifikáció a C#-szintaxis és -használat végleges forrása.