Megosztás a következőn keresztül:


Kivételkezelés (C# programozási útmutató)

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 catch blokk 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.

Lásd még