Sök…


Anmärkningar

Relaterad:

Fånga ett undantag

Koden kan och bör kasta undantag under exceptionella omständigheter. Exempel på detta inkluderar:

Den som ringer kan hantera dessa undantag genom att "fånga" dem och bör bara göra det när:

  • Det kan faktiskt lösa den exceptionella omständigheten eller återhämta sig på lämpligt sätt, eller;
  • Det kan ge ytterligare sammanhang till undantaget som skulle vara användbart om undantaget behöver kastas om (omkastade undantag fångas av undantagshandlare längre upp i samtalstacken)

Det bör noteras att valet att inte fånga ett undantag är helt giltigt om avsikten är att det ska hanteras på en högre nivå.

Att fånga ett undantag görs genom att lägga in den potentiellt kasta koden i ett try { ... } -block enligt följande och fånga de undantag som det kan hantera i en catch (ExceptionType) { ... } -block:

Console.Write("Please enter a filename: ");
string filename = Console.ReadLine();

Stream fileStream;

try
{
    fileStream = File.Open(filename);
}
catch (FileNotFoundException)
{
    Console.WriteLine("File '{0}' could not be found.", filename);
}

Med ett slutligt block

Det finally { ... } blocket av en try-finally eller try-catch-finally kommer alltid att köras, oavsett om ett undantag inträffade eller inte (utom när en StackOverflowException har kastats eller ett samtal har gjorts till Environment.FailFast() ).

Det kan användas för att frigöra eller rensa upp resurser som förvärvats i try { ... } blockera säkert.

Console.Write("Please enter a filename: ");
string filename = Console.ReadLine();

Stream fileStream = null;

try
{
    fileStream = File.Open(filename);
}
catch (FileNotFoundException)
{
    Console.WriteLine("File '{0}' could not be found.", filename);
}
finally
{
    if (fileStream != null)
    {
        fileStream.Dispose();
    }
}

Fånga och återupptagna fångade undantag

När du vill fånga ett undantag och göra något, men du inte kan fortsätta exekveringen av det aktuella kodblocket på grund av undantaget, kanske du vill flytta om undantaget till nästa undantagshanterare i samtalstacken. Det finns bra sätt och dåliga sätt att göra detta.

private static void AskTheUltimateQuestion()
{
    try
    {
        var x = 42;
        var y = x / (x - x); // will throw a DivideByZeroException

        // IMPORTANT NOTE: the error in following string format IS intentional
        // and exists to throw an exception to the FormatException catch, below
        Console.WriteLine("The secret to life, the universe, and everything is {1}", y); 
    }
    catch (DivideByZeroException)
    {
        // we do not need a reference to the exception
        Console.WriteLine("Dividing by zero would destroy the universe.");

        // do this to preserve the stack trace:
        throw;
    }
    catch (FormatException ex)
    {
        // only do this if you need to change the type of the Exception to be thrown 
        // and wrap the inner Exception

        // remember that the stack trace of the outer Exception will point to the
        // next line

        // you'll need to examine the InnerException property to get the stack trace
        // to the line that actually started the problem

        throw new InvalidOperationException("Watch your format string indexes.", ex);
    }
    catch (Exception ex)
    {
        Console.WriteLine("Something else horrible happened. The exception: " + ex.Message);

        // do not do this, because the stack trace will be changed to point to
        // this location instead of the location where the exception
        // was originally thrown:
        throw ex; 
    }
}

static void Main()
{
    try
    {
        AskTheUltimateQuestion();
    }
    catch
    {
        // choose this kind of catch if you don't need any information about 
        // the exception that was caught

        // this block "eats" all exceptions instead of rethrowing them
    }
}

Du kan filtrera efter undantagstyp och till och med efter undantagsegenskaper (nya i C # 6.0, lite längre tillgängligt i VB.NET (citation behövs)):

Dokumentation / C # / nya funktioner

Undantagsfilter

Eftersom C # 6.0 kan undantag filtreras med operatören when .

Detta liknar användning av en enkel if men inte lossar bunten om villkoret inuti when inte är uppfyllt.

Exempel

try
{ 
  // ...
}
catch (Exception e) when (e.InnerException != null) // Any condition can go in here.
{
  // ...
}

Samma information finns i C # 6.0-funktionerna här: Undantagsfilter

Återuppta ett undantag inom ett fångstblock

Inom ett catch kan throw nyckelordet användas på egen hand, utan att ange ett undantagsvärde, för att återkasta undantaget som just fångades. Genom att återta ett undantag kan det ursprungliga undantaget fortsätta uppåt undantagshanteringskedjan och bevara dess samtalstack eller tillhörande data:

try {...}
catch (Exception ex) {
  // Note: the ex variable is *not* used
  throw;
}

Ett vanligt antimönster är att istället throw ex , vilket har effekten att begränsa nästa undantagshandlers syn på stackspåret:

try {...}
catch (Exception ex) {
  // Note: the ex variable is thrown
  //  future stack traces of the exception will not see prior calls
  throw ex;  
}

I allmänhet är det inte önskvärt att använda throw ex , eftersom framtida undantagshanterare som inspekterar stackspåret bara kan se samtal så långt tillbaka som throw ex . Genom att utelämna ex variabeln och bara använda throw nyckelordet kommer det ursprungliga undantaget att "bubbla upp" .

Kasta ett undantag från en annan metod samtidigt som informationen bevaras

Ibland vill du fånga ett undantag och kasta det från en annan tråd eller metod medan du bevarar den ursprungliga undantagsbunten. Detta kan göras med ExceptionDispatchInfo :

using System.Runtime.ExceptionServices;

void Main()
{
    ExceptionDispatchInfo capturedException = null;
    try
    {
        throw new Exception();
    }
    catch (Exception ex)
    {
        capturedException = ExceptionDispatchInfo.Capture(ex);
    }
    
    Foo(capturedException);
}

void Foo(ExceptionDispatchInfo exceptionDispatchInfo)
{
    // Do stuff

    if (capturedException != null)
    {
        // Exception stack trace will show it was thrown from Main() and not from Foo()
        exceptionDispatchInfo.Throw();
    }
}


Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow