Zoeken…


Opmerkingen

Verwant:

Een uitzondering vangen

Code kan en moet uitzonderingen maken in uitzonderlijke omstandigheden. Voorbeelden hiervan zijn:

De beller kan met deze uitzonderingen omgaan door ze te "vangen" en moet dit alleen doen wanneer:

  • Het kan de uitzonderlijke omstandigheid oplossen of op de juiste manier herstellen, of;
  • Het kan een extra context bieden voor de uitzondering die nuttig zou zijn als de uitzondering opnieuw moet worden gegenereerd (uitzonderingen worden opnieuw opgevangen door uitzonderingsbehandelaars verderop in de oproepstack)

Opgemerkt dient te worden dat de keuze niet om een uitzondering te vangen is volkomen geldig als het de bedoeling is om het op een hoger niveau worden behandeld.

Het vangen van een uitzondering wordt gedaan door de potentieel gooiende code als volgt in een try { ... } -blok te wikkelen en de uitzonderingen te vangen die het kan verwerken in een catch (ExceptionType) { ... } -blok:

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

Eindelijk een blok gebruiken

Het finally { ... } blok van een try-finally of try-catch-finally zal altijd worden uitgevoerd, ongeacht of er een uitzondering is opgetreden of niet (behalve wanneer een StackOverflowException is gegenereerd of een aanroep is gedaan naar Environment.FailFast() ).

Het kan worden gebruikt om bronnen die zijn verkregen in het try { ... } -blok veilig vrij te maken of op te ruimen.

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

Gevangen uitzonderingen vangen en opnieuw werpen

Wanneer u een uitzondering wilt opvangen en iets wilt doen, maar u vanwege de uitzondering niet door kunt gaan met de uitvoering van het huidige codeblok, wilt u de uitzondering mogelijk doorsturen naar de volgende uitzonderingshandler in de call-stack. Er zijn goede manieren en slechte manieren om dit te doen.

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

U kunt filteren op uitzonderingstype en zelfs op uitzonderingseigenschappen (nieuw in C # 6.0, iets langer beschikbaar in VB.NET (nodig citaat)):

Documentatie / C # / nieuwe functies

Uitzonderingsfilters

Omdat C # 6.0-uitzonderingen kunnen worden gefilterd met de operator when .

Dit is vergelijkbaar met het gebruik van een eenvoudige if maar rolt de stapel niet af als niet aan de voorwaarde in het when wordt voldaan.

Voorbeeld

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

Dezelfde info vindt u hier in de C # 6.0-functies : Uitzonderingsfilters

Een uitzondering opnieuw uitwerken binnen een vangblok

Binnen een catch blok kan het throw trefwoord op zichzelf worden gebruikt, zonder een uitzonderingswaarde op te geven, om de uitzondering te vangen die zojuist is gevangen. Door een uitzondering opnieuw te verwerken, kan de oorspronkelijke uitzondering doorgaan in de afhandelingsketen voor uitzonderingen, waarbij de oproepstack of bijbehorende gegevens behouden blijven:

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

Een veel voorkomend antipatroon is om in plaats daarvan throw ex te throw ex , wat tot gevolg heeft dat de weergave van de volgende uitzonderingshandler op de stacktracering wordt beperkt:

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

Over het algemeen is het gebruik van throw ex niet wenselijk, aangezien toekomstige uitzonderingshandlers die de stack-trace inspecteren, alleen oproepen kunnen zien die teruggaan tot throw ex . Door de ex variabele weg te laten en alleen het sleutelwoord throw gebruiken, wordt de oorspronkelijke uitzondering "opgedroogd" .

Een uitzondering maken van een andere methode met behoud van de informatie

Af en toe wil je een uitzondering vangen en deze uit een andere thread of methode gooien met behoud van de oorspronkelijke uitzonderingsstapel. Dit kan worden gedaan met 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
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow