Zoeken…


Basisafhandeling van uitzonderingen

try
{
    /* code that could throw an exception */
}
catch (Exception ex)
{
    /* handle the exception */
}

Merk op dat het omgaan met alle uitzonderingen met dezelfde code vaak niet de beste aanpak is.
Dit wordt meestal gebruikt als een interne uitzonderingsafhandelingsroutines mislukken, als laatste redmiddel.

Omgaan met specifieke uitzonderingen

try
{
    /* code to open a file */
}
catch (System.IO.FileNotFoundException)
{
    /* code to handle the file being not found */
}
catch (System.IO.UnauthorizedAccessException)
{
    /* code to handle not being allowed access to the file */
}
catch (System.IO.IOException)
{
    /* code to handle IOException or it's descendant other than the previous two */
}
catch (System.Exception)
{
    /* code to handle other errors */
}

Zorg ervoor dat uitzonderingen in volgorde worden geëvalueerd en dat overerving wordt toegepast. Je moet dus beginnen met de meest specifieke en eindigen met hun voorouder. Op elk gegeven moment wordt slechts één catch-blok uitgevoerd.

Het uitzonderingsobject gebruiken

Je mag uitzonderingen maken en in je eigen code gooien. Het instantiëren van een uitzondering gebeurt op dezelfde manier als elk ander C # -object.

Exception ex = new Exception();

// constructor with an overload that takes a message string
Exception ex = new Exception("Error message"); 

U kunt vervolgens het trefwoord throw gebruiken om de uitzondering te verhogen:

try
{
    throw new Exception("Error");
}
catch (Exception ex)
{
    Console.Write(ex.Message); // Logs 'Error' to the output window
} 

Opmerking: als u een nieuwe uitzondering in een blokkeerblok gooit, moet u ervoor zorgen dat de oorspronkelijke uitzondering wordt doorgegeven als "innerlijke uitzondering", bijvoorbeeld

void DoSomething() 
{
    int b=1; int c=5;
    try
    {
        var a = 1; 
        b = a - 1;
        c = a / b;
        a = a / c;
    }        
    catch (DivideByZeroException dEx) when (b==0)
    {
        // we're throwing the same kind of exception
        throw new DivideByZeroException("Cannot divide by b because it is zero", dEx);
    }
    catch (DivideByZeroException dEx) when (c==0)
    {
        // we're throwing the same kind of exception
        throw new DivideByZeroException("Cannot divide by c because it is zero", dEx);
    }
}

void Main()
{    
    try
    {
        DoSomething();
    }
    catch (Exception ex)
    {
        // Logs full error information (incl. inner exception)
        Console.Write(ex.ToString()); 
    }    
}

In dit geval wordt ervan uitgegaan dat de uitzondering niet kan worden afgehandeld, maar wordt enige nuttige informatie aan het bericht toegevoegd (en de oorspronkelijke uitzondering is nog steeds toegankelijk via ex.InnerException door een buitenste uitzonderingsblok).

Het zal iets laten zien als:

System.DivideByZeroException: kan niet delen door b omdat het nul is ---> System.DivideByZeroException: geprobeerd te delen door nul.
op UserQuery.g__DoSomething0_0 () in C: [...] \ LINQPadQuery.cs: regel 36
--- Einde van innerlijke uitzonderingsstapeltrace ---
op UserQuery.g__DoSomething0_0 () in C: [...] \ LINQPadQuery.cs: regel 42
bij UserQuery.Main () in C: [...] \ LINQPadQuery.cs: regel 55

Als je dit voorbeeld in LinqPad probeert, zul je merken dat de regelnummers niet erg zinvol zijn (ze helpen je niet altijd). Maar het doorgeven van een nuttige fouttekst, zoals hierboven gesuggereerd, vermindert vaak de tijd om de locatie van de fout op te sporen, wat in dit voorbeeld duidelijk de lijn is

c = a / b;

in functie DoSomething() .

Probeer het in .NET Fiddle

Eindelijk blok

try
{
    /* code that could throw an exception */
}
catch (Exception)
{
    /* handle the exception */
}
finally
{
    /* Code that will be executed, regardless if an exception was thrown / caught or not */
}

Het try / catch / finally blok kan erg handig zijn bij het lezen van bestanden.
Bijvoorbeeld:

FileStream f = null;

try
{
    f = File.OpenRead("file.txt");
    /* process the file here */
}
finally
{
    f?.Close(); // f may be null, so use the null conditional operator.
}

Een blok try moet worden gevolgd door ofwel een catch of een finally blok. Aangezien er echter geen catch-blok is, zal de uitvoering de beëindiging veroorzaken. Voor beëindiging worden de instructies in het slotblok uitgevoerd.

Bij het lezen van bestanden hadden we een using gebruiken als FileStream (wat OpenRead retourneert) IDisposable .

Zelfs als er een return statement in try blok, het finally zal blok meestal uit te voeren; er zijn een paar gevallen waarin dit niet het geval is:

Implementeren van IErrorHandler voor WCF Services

De implementatie van IErrorHandler voor WCF-services is een geweldige manier om foutafhandeling en logboekregistratie te centraliseren. De hier getoonde implementatie zou elke onverwerkte uitzondering moeten opvangen die wordt gegenereerd als gevolg van een oproep aan een van uw WCF-services. In dit voorbeeld wordt ook getoond hoe een aangepast object wordt geretourneerd en hoe JSON wordt geretourneerd in plaats van de standaard XML.

Implementeer IErrorHandler:

using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
using System.Runtime.Serialization.Json;
using System.ServiceModel;
using System.ServiceModel.Web;

namespace BehaviorsAndInspectors
{
    public class ErrorHandler : IErrorHandler
    {

        public bool HandleError(Exception ex)
        {
            // Log exceptions here

            return true;

        } // end

        public void ProvideFault(Exception ex, MessageVersion version, ref Message fault)
        {
            // Get the outgoing response portion of the current context
            var response = WebOperationContext.Current.OutgoingResponse;

            // Set the default http status code 
            response.StatusCode = HttpStatusCode.InternalServerError;

            // Add ContentType header that specifies we are using JSON
            response.ContentType = new MediaTypeHeaderValue("application/json").ToString();

            // Create the fault message that is returned (note the ref parameter) with BaseDataResponseContract                
            fault = Message.CreateMessage(
                version,
                string.Empty,
                new CustomReturnType { ErrorMessage = "An unhandled exception occurred!" },
                new DataContractJsonSerializer(typeof(BaseDataResponseContract), new List<Type> { typeof(BaseDataResponseContract) }));

            if (ex.GetType() == typeof(VariousExceptionTypes))
            {
                 // You might want to catch different types of exceptions here and process them differently
            }

            // Tell WCF to use JSON encoding rather than default XML
            var webBodyFormatMessageProperty = new WebBodyFormatMessageProperty(WebContentFormat.Json);
            fault.Properties.Add(WebBodyFormatMessageProperty.Name, webBodyFormatMessageProperty);

        } // end

    } // end class

} // end namespace

In dit voorbeeld koppelen we de handler aan het servicegedrag. U kunt dit ook op dezelfde manier koppelen aan IEndpointBehavior, IContractBehavior of IOperationBehavior.

Hechten aan servicegedrag:

using System;
using System.Collections.ObjectModel;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Configuration;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;

namespace BehaviorsAndInspectors
{
    public class ErrorHandlerExtension : BehaviorExtensionElement, IServiceBehavior
    {
        public override Type BehaviorType
        {
            get { return GetType(); }
        }

        protected override object CreateBehavior()
        {
            return this;
        }

        private IErrorHandler GetInstance()
        {
            return new ErrorHandler();
        }

        void IServiceBehavior.AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) { } // end

        void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
            var errorHandlerInstance = GetInstance();

            foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers)
            {
                dispatcher.ErrorHandlers.Add(errorHandlerInstance);
            }
        }

        void IServiceBehavior.Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { } // end
      
    } // end class

} // end namespace

Configs in Web.config:

...
<system.serviceModel>

    <services>      
      <service name="WebServices.MyService">
        <endpoint binding="webHttpBinding" contract="WebServices.IMyService" />
      </service>
    </services>

    <extensions>      
      <behaviorExtensions>        
        <!-- This extension if for the WCF Error Handling-->
        <add name="ErrorHandlerBehavior" type="WebServices.BehaviorsAndInspectors.ErrorHandlerExtensionBehavior, WebServices, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />      
      </behaviorExtensions>    
    </extensions>

    <behaviors>          
      <serviceBehaviors>        
        <behavior>
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="true"/>
          <ErrorHandlerBehavior />
        </behavior>     
      </serviceBehaviors>    
    </behaviors>

    ....
</system.serviceModel>
...

Hier zijn een paar links die nuttig kunnen zijn over dit onderwerp:

https://msdn.microsoft.com/en-us/library/system.servicemodel.dispatcher.ierrorhandler(v=vs.100).aspx

http://www.brainthud.com/cards/5218/25441/which-four-behavior-interfaces-exist-for-interacting-with-a-service-or-client-description-what-methods-do-they- implementeren en

Andere voorbeelden:

IErrorHandler retourneert verkeerde berichttekst wanneer HTTP-statuscode 401 Ongeautoriseerd is

IErrorHandler lijkt mijn fouten in WCF niet te verwerken ... enig idee?

Hoe een aangepaste WCF-foutafhandelaar een JSON-antwoord met een niet-OK http-code te maken?

Hoe stel je de Content-Type header in voor een HttpClient-verzoek?

Aangepaste uitzonderingen maken

U mag aangepaste uitzonderingen implementeren die net als elke andere uitzondering kunnen worden gegenereerd. Dit is zinvol wanneer u uw uitzonderingen tijdens runtime wilt onderscheiden van andere fouten.

In dit voorbeeld maken we een aangepaste uitzondering voor een duidelijke afhandeling van problemen die de toepassing kan hebben tijdens het parseren van een complexe invoer.

Aangepaste uitzonderingsklasse maken

Om een aangepaste uitzondering te maken, maakt u een subklasse van Exception :

public class ParserException : Exception
{
    public ParserException() : 
      base("The parsing went wrong and we have no additional information.") { }
}

Aangepaste uitzondering wordt erg handig wanneer u extra informatie aan de catcher wilt geven:

public class ParserException : Exception
{
    public ParserException(string fileName, int lineNumber) : 
      base($"Parser error in {fileName}:{lineNumber}") 
    {
      FileName = fileName;
      LineNumber = lineNumber;
    }
    public string FileName {get; private set;}
    public int LineNumber {get; private set;}    
}

Wanneer u nu catch(ParserException x) hebt u extra semantiek om de afhandeling van uitzonderingen te verfijnen.

Aangepaste klassen kunnen de volgende functies implementeren om aanvullende scenario's te ondersteunen.

re-gooien

Tijdens het parseren is de oorspronkelijke uitzondering nog steeds interessant. In dit voorbeeld is het een FormatException omdat de code probeert een string te ontleden, die naar verwachting een getal zal zijn. In dit geval moet de aangepaste uitzondering de opname van de ' InnerException ' ondersteunen:

//new constructor:
ParserException(string msg, Exception inner) : base(msg, inner) {
}

serialisatie

In sommige gevallen kunnen uw uitzonderingen de grenzen van AppDomain overschrijden. Dit is het geval als uw parser in zijn eigen AppDomain wordt uitgevoerd om hot reloading van nieuwe parserconfiguraties te ondersteunen. In Visual Studio kunt u de Exception gebruiken om dergelijke code te genereren.

[Serializable]
public class ParserException : Exception
{
    // Constructor without arguments allows throwing your exception without
    // providing any information, including error message. Should be included
    // if your exception is meaningful without any additional details. Should
    // set message by calling base constructor (default message is not helpful).
    public ParserException()
        : base("Parser failure.")
    {}

    // Constructor with message argument allows overriding default error message.
    // Should be included if users can provide more helpful messages than
    // generic automatically generated messages.
    public ParserException(string message) 
        : base(message)
    {}

    // Constructor for serialization support. If your exception contains custom
    // properties, read their values here.
    protected ParserException(SerializationInfo info, StreamingContext context) 
        : base(info, context)
    {}
}

De ParserException gebruiken

try
{
    Process.StartRun(fileName)
}
catch (ParserException ex)
{
    Console.WriteLine($"{ex.Message} in ${ex.FileName}:${ex.LineNumber}");
}
catch (PostProcessException x) 
{
    ...
}

U kunt ook aangepaste uitzonderingen gebruiken voor het vangen en inpakken van uitzonderingen. Op deze manier kunnen veel verschillende fouten worden omgezet in een enkel fouttype dat nuttiger is voor de toepassing:

try
{
    int foo = int.Parse(token);
}
catch (FormatException ex)
{
    //Assuming you added this constructor
    throw new ParserException(
      $"Failed to read {token} as number.", 
      FileName, 
      LineNumber, 
      ex);
}

Wanneer u uitzonderingen behandelt door uw eigen aangepaste uitzonderingen te verhogen, moet u meestal een verwijzing naar de oorspronkelijke uitzondering opnemen in de eigenschap InnerException , zoals hierboven weergegeven.

Bezorgdheid over de beveiliging

Als het blootleggen van de reden voor de uitzondering de beveiliging in gevaar kan brengen doordat gebruikers de interne werking van uw toepassing kunnen zien, kan het een slecht idee zijn om de interne uitzondering te omzeilen. Dit kan van toepassing zijn als u een klassenbibliotheek maakt die door anderen wordt gebruikt.

Hier is hoe je een aangepaste uitzondering kunt maken zonder de binnenste uitzondering te verpakken:

try
{
  // ...
}
catch (SomeStandardException ex)
{
  // ...
  throw new MyCustomException(someMessage);
}

Conclusie

Wanneer u een aangepaste uitzondering oproept (met omloop of met een nieuwe onverpakte uitzondering), moet u een uitzondering opwerpen die zinvol is voor de beller. Een gebruiker van een klassenbibliotheek kan bijvoorbeeld niet veel weten over hoe die bibliotheek zijn interne werk doet. De uitzonderingen die worden veroorzaakt door de afhankelijkheden van de klassenbibliotheek, hebben geen betekenis. De gebruiker wil eerder een uitzondering die relevant is voor de manier waarop de klassenbibliotheek die afhankelijkheden op een verkeerde manier gebruikt.

try
{
  // ...
}
catch (IOException ex)
{
  // ...
  throw new StorageServiceException(@"The Storage Service encountered a problem saving
your data. Please consult the inner exception for technical details. 
If you are not able to resolve the problem, please call 555-555-1234 for technical       
assistance.", ex);
}

Uitzondering anti-patronen

Uitzonderingen slikken

Men moet de uitzondering altijd op de volgende manier opnieuw gooien:

try
{
    ...
}
catch (Exception ex)
{
    ...
    throw;
}

Het opnieuw gooien van een uitzondering zoals hieronder zal de oorspronkelijke uitzondering verdoezelen en zal het originele stapeltrace verliezen. Men zou dit nooit moeten doen! De stapelspoor voorafgaand aan de vangst en opnieuw gegooid gaat verloren.

try
{
    ...
}
catch (Exception ex)
{
    ...
    throw ex;
}

Honkbaluitzondering afhandeling

Men moet geen uitzonderingen gebruiken als vervanging voor normale flow control constructies zoals if-then statements en while-lussen. Dit anti-patroon wordt ook wel Baseball Exception Handling genoemd .

Hier is een voorbeeld van het anti-patroon:

try
{
    while (AccountManager.HasMoreAccounts())
    {
        account = AccountManager.GetNextAccount();
        if (account.Name == userName)
        {
            //We found it
            throw new AccountFoundException(account);
        }
    }
}
catch (AccountFoundException found)
{
    Console.Write("Here are your account details: " + found.Account.Details.ToString());
}

Hier is een betere manier om het te doen:

Account found = null;
while (AccountManager.HasMoreAccounts() && (found==null))
{
    account = AccountManager.GetNextAccount();
    if (account.Name == userName)
    {
        //We found it
        found = account;
    }
}
Console.Write("Here are your account details: " + found.Details.ToString());

vangen (uitzondering)

Er zijn bijna geen (sommigen zeggen geen!) Redenen om het generieke uitzonderingstype in uw code te vangen. Je zou alleen de uitzonderingen moeten vangen die je verwacht, omdat je anders bugs in je code verbergt.

try 
{
     var f = File.Open(myfile);
     // do something
}
catch (Exception x)
{
     // Assume file not found
     Console.Write("Could not open file");
     // but maybe the error was a NullReferenceException because of a bug in the file handling code?
}

Beter doen:

try 
{
     var f = File.Open(myfile);
     // do something which should normally not throw exceptions
}
catch (IOException)
{
     Console.Write("File not found");
}
// Unfortunatelly, this one does not derive from the above, so declare separatelly
catch (UnauthorizedAccessException) 
{
     Console.Write("Insufficient rights");
}

Als er een andere uitzondering gebeurt, hebben we de toepassing opzettelijk laten crashen, zodat deze rechtstreeks in de debugger stapt en we het probleem kunnen oplossen. We moeten geen programma verzenden waar andere uitzonderingen dan toch optreden, dus het is geen probleem om een crash te hebben.

Het volgende is ook een slecht voorbeeld, omdat het uitzonderingen gebruikt om een programmeerfout te omzeilen. Daar zijn ze niet voor ontworpen.

public void DoSomething(String s)
{
     if (s == null)
         throw new ArgumentNullException(nameof(s));
     // Implementation goes here
}

try 
{    
     DoSomething(myString);
}
catch(ArgumentNullException x)
{
    // if this happens, we have a programming error and we should check
    // why myString was null in the first place.
}

Verzamel uitzonderingen / meerdere uitzonderingen van één methode

Wie zegt dat je niet in één methode meerdere uitzonderingen kunt maken. Als je niet gewend bent om met AggregateExceptions te spelen, kun je in de verleiding komen om je eigen datastructuur te maken om veel dingen weer te geven die fout gaan. Er zijn natuurlijk nog een andere datastructuur die geen uitzondering is, idealer, zoals de resultaten van een validatie. Zelfs als je met AggregateExceptions speelt, sta je misschien aan de ontvangende kant en behandel je ze altijd zonder je te realiseren dat ze je kunnen helpen.

Het is heel aannemelijk om een methode uit te voeren en hoewel het een hele fout zal zijn, wil je meerdere dingen benadrukken die fout zijn gegaan in de uitzonderingen die worden gegooid. Als een voorbeeld kan dit gedrag worden gezien met de manier waarop Parallelle methoden werken, een taak die in meerdere threads is onderverdeeld en een willekeurig aantal van hen kan uitzonderingen genereren en dit moet worden gemeld. Hier is een dom voorbeeld van hoe u hiervan kunt profiteren:

    public void Run()
    {
        try
        {
            this.SillyMethod(1, 2);
        }
        catch (AggregateException ex)
        {
            Console.WriteLine(ex.Message);
            foreach (Exception innerException in ex.InnerExceptions)
            {
                Console.WriteLine(innerException.Message);
            }
        }
    }

    private void SillyMethod(int input1, int input2)
    {
        var exceptions = new List<Exception>();

        if (input1 == 1)
        {
            exceptions.Add(new ArgumentException("I do not like ones"));
        }
        if (input2 == 2)
        {
            exceptions.Add(new ArgumentException("I do not like twos"));
        }
        if (exceptions.Any())
        {
            throw new AggregateException("Funny stuff happended during execution", exceptions);
        }
    }

Nesten van uitzonderingen en probeer blokken te vangen.

Men is in staat om de ene uitzondering te nestelen / try blok in de andere try catch .

Op deze manier kan men kleine blokken code beheren die kunnen werken zonder uw hele mechanisme te verstoren.

try 
{
//some code here
    try 
    {
        //some thing which throws an exception. For Eg : divide by 0
    }
    catch (DivideByZeroException dzEx)
    {
        //handle here only this exception
        //throw from here will be passed on to the parent catch block
    }
    finally
    {
        //any thing to do after it is done.
    }
 //resume from here & proceed as normal; 
}
catch(Exception e)
{
    //handle here
}

Opmerking: vermijd het inslikken van uitzonderingen bij het gooien naar het ouderblok

Best practices

Spiek briefje

DOEN DO NOT
Controle stroom met controle verklaringen Regelingsstroom met uitzonderingen
Houd genegeerde (geabsorbeerde) uitzonderingen bij door te loggen Negeer uitzondering
Herhaal de uitzondering met de throw Re-throw exception - throw new ArgumentNullException() of throw ex
Gooi vooraf gedefinieerde systeemuitzonderingen Gooi aangepaste uitzonderingen op dezelfde manier als vooraf gedefinieerde systeemuitzonderingen
Gebruik aangepaste / vooraf gedefinieerde uitzonderingen als dit cruciaal is voor de toepassingslogica Gooi aangepaste / vooraf gedefinieerde uitzonderingen om een waarschuwing in flow aan te geven
Vang uitzonderingen die u wilt verwerken Vang elke uitzondering

Beheer bedrijfslogica NIET met uitzonderingen.

Flowregeling mag NIET door uitzonderingen worden gedaan. Gebruik in plaats daarvan voorwaardelijke verklaringen. Als een controle duidelijk kan worden gedaan met de instructie if-else , gebruik dan geen uitzonderingen omdat dit de leesbaarheid en prestaties vermindert.

Overweeg het volgende fragment van Mr. Bad Practices:

// This is a snippet example for DO NOT
object myObject;
void DoingSomethingWithMyObject()
{
    Console.WriteLine(myObject.ToString());
}

Wanneer de uitvoering Console.WriteLine(myObject.ToString()); bereikt Console.WriteLine(myObject.ToString()); applicatie gooit een NullReferenceException. De heer Bad Practices realiseerde zich dat myObject nul is en bewerkte zijn fragment om NullReferenceException te vangen en af te handelen:

// This is a snippet example for DO NOT
object myObject;
void DoingSomethingWithMyObject()
{
    try
    {
        Console.WriteLine(myObject.ToString());
    }
    catch(NullReferenceException ex)
    {
        // Hmmm, if I create a new instance of object and assign it to myObject:
        myObject = new object();
        // Nice, now I can continue to work with myObject
        DoSomethingElseWithMyObject();
    }
}

Aangezien het vorige fragment alleen de uitzonderingslogica bevat, wat moet ik doen als myObject op dit moment niet nul is? Waar moet ik dit deel van de logica behandelen? Direct na Console.WriteLine(myObject.ToString()); ? Hoe zit het na het try...catch blok try...catch ?

Hoe zit het met Mr. Best Practices? Hoe zou hij hiermee omgaan?

// This is a snippet example for DO
object myObject;
void DoingSomethingWithMyObject()
{
    if(myObject == null)
        myObject = new object();
    
    // When execution reaches this point, we are sure that myObject is not null
    DoSomethingElseWithMyObject();
}

De heer Best Practices bereikte dezelfde logica met minder code en een duidelijke en begrijpelijke logica.

Gooi uitzonderingen NIET opnieuw

Uitgooien van uitzonderingen is duur. Het heeft een negatieve invloed op de prestaties. Voor code die routinematig faalt, kunt u ontwerppatronen gebruiken om prestatieproblemen te minimaliseren. In dit onderwerp worden twee ontwerppatronen beschreven die handig zijn wanneer uitzonderingen de prestaties aanzienlijk kunnen beïnvloeden.

Absorbeer GEEN uitzonderingen zonder logboekregistratie

try
{
    //Some code that might throw an exception
}
catch(Exception ex)
{
    //empty catch block, bad practice
}

Slik nooit uitzonderingen door. Het negeren van uitzonderingen zal dat moment redden maar zal later een chaos creëren voor onderhoudbaarheid. Wanneer u uitzonderingen vastlegt, moet u altijd de uitzonderingsinstantie registreren, zodat de volledige stacktracering wordt vastgelegd en niet alleen het uitzonderingsbericht.

try
{
    //Some code that might throw an exception
}
catch(NullException ex)
{
    LogManager.Log(ex.ToString());
}

Vang geen uitzonderingen die u niet aan kunt

Veel bronnen, zoals deze , dringen er sterk op aan om na te denken waarom u een uitzondering maakt op de plaats waar u deze opvangt. Je zou alleen een uitzondering moeten vangen als je het op die locatie aankan. Als je daar iets kunt doen om het probleem te verminderen, zoals een alternatief algoritme proberen, verbinding maken met een back-updatabase, een andere bestandsnaam proberen, 30 seconden wachten en het opnieuw proberen, of een beheerder op de hoogte brengen, kun je de fout opmerken en dat doen. Als er niets is dat u aannemelijk en redelijkerwijs kunt doen, "laat het dan los" en laat de uitzondering op een hoger niveau worden afgehandeld. Als de uitzondering voldoende catastrofaal is en er geen redelijke optie is, behalve dat het hele programma crasht vanwege de ernst van het probleem, laat het dan crashen.

try
{
    //Try to save the data to the main database.
}
catch(SqlException ex)
{
    //Try to save the data to the alternative database.
}
//If anything other than a SqlException is thrown, there is nothing we can do here. Let the exception bubble up to a level where it can be handled.

Onbehandelde en thread-uitzondering

AppDomain.UnhandledException Deze gebeurtenis geeft een melding van niet-ingevulde uitzonderingen. Hiermee kan de toepassing informatie over de uitzondering registreren voordat de standaardhandler van het systeem de uitzondering aan de gebruiker meldt en de toepassing beëindigt. Als er voldoende informatie beschikbaar is over de status van de toepassing, acties kunnen worden ondernomen - zoals het opslaan van programmagegevens voor later herstel. Voorzichtigheid is geboden, omdat programmagegevens beschadigd kunnen raken wanneer uitzonderingen niet worden verwerkt.

    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    private static void Main(string[] args)
    {
        AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(UnhandledException);            
    }

Application.ThreadException Met deze gebeurtenis kan uw Windows Forms-toepassing anders onverwerkte uitzonderingen verwerken die voorkomen in Windows Forms-threads. Koppel uw gebeurtenishandlers aan de ThreadException-gebeurtenis om met deze uitzonderingen om te gaan, waardoor uw toepassing in een onbekende staat blijft. Waar mogelijk moeten uitzonderingen worden afgehandeld door een gestructureerd uitzonderingsafhandelingsblok.

    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    private static void Main(string[] args)
    {
        AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(UnhandledException);
        Application.ThreadException += new ThreadExceptionEventHandler(ThreadException);
    }

En tot slot de afhandeling van uitzonderingen

static void UnhandledException(object sender, UnhandledExceptionEventArgs e)
    {
        Exception ex = (Exception)e.ExceptionObject;
        // your code
    }

static void ThreadException(object sender, ThreadExceptionEventArgs e)
    {
        Exception ex = e.Exception;
        // your code
    }

Een uitzondering gooien

Uw code kan en moet vaak een uitzondering genereren wanneer er iets ongewoons is gebeurd.

public void WalkInto(Destination destination)
{
    if (destination.Name == "Mordor")
    {
        throw new InvalidOperationException("One does not simply walk into Mordor.");
    }
    // ... Implement your normal walking code here.
}


Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow