Dela via


Undantagshantering (C#-programmeringsguide)

Ett försöksblock används av C#-programmerare för att partitioneras kod som kan påverkas av ett undantag. Associerade fångstblock används för att hantera eventuella resulterande undantag. Ett slutligen block innehåller kod som körs oavsett om ett undantag genereras i try blocket eller inte, till exempel frigöra resurser som har allokerats i try blocket. Ett try block kräver ett eller flera associerade catch block, ett finally block eller båda.

I följande exempel visas en try-catch -instruktion, en try-finally -instruktion och en try-catch-finally -instruktion.

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.
}

Ett try block utan ett catch eller finally ett block orsakar ett kompilatorfel.

Fånga block

Ett catch block kan ange vilken typ av undantag som ska fångas. Typspecifikationen kallas för ett undantagsfilter. Undantagstypen ska härledas från Exception. I allmänhet anger du Exception inte som undantagsfilter om du inte vet hur du hanterar alla undantag som kan genereras i try blocket, eller om du har inkluderat en throw instruktion i slutet av blocket catch .

Flera catch block med olika undantagsklasser kan länkas samman. Blocken catch utvärderas uppifrån och ned i koden, men endast ett catch block körs för varje undantag som genereras. Det första catch blocket som anger den exakta typen eller en basklass för undantaget som genereras körs. Om inget catch block anger en matchande undantagsklass väljs ett catch block som inte har någon typ, om det finns en i -instruktionen. Det är viktigt att placera catch block med de mest specifika undantagsklasserna (dvs. de mest härledda).

Fånga undantag när följande villkor är uppfyllda:

  • Du har en god förståelse för varför undantaget kan genereras och du kan implementera en specifik återställning, till exempel att uppmana användaren att ange ett nytt filnamn när du fångar ett FileNotFoundException objekt.
  • Du kan skapa och skapa ett nytt, mer specifikt undantag.
    int GetInt(int[] array, int index)
    {
        try
        {
            return array[index];
        }
        catch (IndexOutOfRangeException e)
        {
            throw new ArgumentOutOfRangeException(
                "Parameter index is out of range.", e);
        }
    }
    
  • Du vill delvis hantera ett undantag innan du skickar det för mer hantering. I följande exempel används ett catch block för att lägga till en post i en fellogg innan undantaget ändras.
    try
    {
        // Try to access a resource.
    }
    catch (UnauthorizedAccessException e)
    {
        // Call a custom error logging procedure.
        LogError(e);
        // Re-throw the error.
        throw;
    }
    

Du kan också ange undantagsfilter för att lägga till ett booleskt uttryck i en catch-sats. Undantagsfilter anger att en specifik catch-sats endast matchar när villkoret är sant. I följande exempel använder båda catch-satserna samma undantagsklass, men ett extra villkor kontrolleras för att skapa ett annat felmeddelande:

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);
    }
}

Ett undantagsfilter som alltid returnerar false kan användas för att undersöka alla undantag men inte bearbeta dem. En vanlig användning är att logga undantag:

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;
    }
}

Metoden LogException returnerar falsealltid , ingen sats catch med hjälp av det här undantagsfiltret matchar. Catch-satsen kan vara allmän, med hjälp av System.Exception, och senare satser kan bearbeta mer specifika undantagsklasser.

Slutligen block

Med ett finally block kan du rensa åtgärder som utförs i ett try block. Om det finally finns körs blocket sist, efter try blocket och alla matchade catch block. Ett finally block körs alltid, oavsett om ett undantag utlöses eller om ett catch block som matchar undantagstypen hittas.

Blocket finally kan användas för att frigöra resurser som filströmmar, databasanslutningar och grafikhandtag utan att vänta på att skräpinsamlaren i körningen ska slutföra objekten.

I följande exempel finally används blocket för att stänga en fil som öppnas i try blocket. Observera att filreferensens tillstånd kontrolleras innan filen stängs. try Om blocket inte kan öppna filen har filhandtaget fortfarande värdet null och finally blocket försöker inte stänga den. Om filen i stället har öppnats i try blocket stänger blocket den finally öppna filen.

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();
}

Språkspecifikation för C#

Mer information finns i Undantag och Try-instruktioneni C#-språkspecifikationen. Språkspecifikationen är den slutgiltiga källan för C#-syntax och -användning.

Se även