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 false
alltid , 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.