Recherche…


Gestion des exceptions de base

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

Notez que la gestion de toutes les exceptions avec le même code n'est souvent pas la meilleure approche.
Ceci est couramment utilisé lorsque toutes les routines de gestion des exceptions internes échouent, en dernier recours.

Gestion de types d'exceptions spécifiques

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

Veillez à ce que les exceptions soient évaluées dans l'ordre et l'héritage est appliqué. Vous devez donc commencer par les plus spécifiques et terminer par leur ancêtre. A tout moment, un seul bloc catch sera exécuté.

Utiliser l'objet exception

Vous êtes autorisé à créer et à lancer des exceptions dans votre propre code. L'instanciation d'une exception se fait de la même manière que tout autre objet C #.

Exception ex = new Exception();

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

Vous pouvez ensuite utiliser le mot-clé throw pour déclencher l'exception:

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

Remarque: Si vous lancez une nouvelle exception dans un bloc catch, vérifiez que l'exception d'origine est transmise en tant qu '"exception interne", par exemple

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

Dans ce cas, il est supposé que l'exception ne peut pas être gérée mais certaines informations utiles sont ajoutées au message (et l'exception d'origine peut toujours être accédée via ex.InnerException par un bloc d'exception externe).

Il montrera quelque chose comme:

System.DivideByZeroException: impossible de diviser par b car il est zéro ---> System.DivideByZeroException: tentative de division par zéro.
à UserQuery.g__DoSomething0_0 () dans C: [...] \ LINQPadQuery.cs: ligne 36
--- Fin de trace de pile d'exception interne ---
à UserQuery.g__DoSomething0_0 () dans C: [...] \ LINQPadQuery.cs: ligne 42
à UserQuery.Main () dans C: [...] \ LINQPadQuery.cs: ligne 55

Si vous essayez cet exemple dans LinqPad, vous remarquerez que les numéros de ligne ne sont pas très significatifs (ils ne vous aident pas toujours). Cependant, le fait de transmettre un texte d'erreur utile, comme suggéré ci-dessus, réduit considérablement le temps nécessaire pour localiser l'erreur, ce qui est clairement dans cet exemple la ligne

c = a / b;

dans la fonction DoSomething() .

Essayez-le avec .NET Fiddle

Bloquer enfin

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

Le bloc try / catch / finally peut être très utile lors de la lecture de fichiers.
Par exemple:

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

Un bloc try doit être suivi soit d'un bloc catch soit d'un bloc finally . Cependant, comme il n'y a pas de bloc catch, l'exécution provoquera une terminaison. Avant la fin, les instructions contenues dans le bloc finally seront exécutées.

Dans la lecture de fichiers, nous aurions pu utiliser un bloc using FileStream (ce OpenRead renvoie OpenRead ) implémente IDisposable .

Même s'il existe une instruction de return dans le bloc try , le bloc finally sera généralement exécuté; il y a quelques cas où cela ne va pas:

Implémentation d'IErrorHandler pour les services WCF

L'implémentation d'IErrorHandler pour les services WCF est un excellent moyen de centraliser la gestion des erreurs et la journalisation. L'implémentation présentée ici doit intercepter toute exception non gérée à la suite d'un appel à l'un de vos services WCF. Cet exemple montre également comment renvoyer un objet personnalisé et comment renvoyer JSON plutôt que le code XML par défaut.

Implémenter 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

Dans cet exemple, nous attachons le gestionnaire au comportement du service. Vous pouvez également associer ceci à IEndpointBehavior, IContractBehavior ou IOperationBehavior de la même manière.

Attacher aux comportements de service:

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

Voici quelques liens utiles sur ce sujet:

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

http://www.brainthud.com/cards/5218/25441/qui-four-behavior-interfaces-exist-for-interact-with-a-service-or-client-description-what-methods-do-they- mettre en œuvre et

Autres exemples:

IErrorHandler renvoie un corps de message incorrect lorsque le code d'état HTTP est 401 Non autorisé

IErrorHandler ne semble pas gérer mes erreurs dans WCF .. des idées?

Comment faire pour que le gestionnaire d'erreurs WCF personnalisé renvoie une réponse JSON avec un code HTTP non OK?

Comment définissez-vous l'en-tête Content-Type pour une requête HttpClient?

Création d'exceptions personnalisées

Vous êtes autorisé à implémenter des exceptions personnalisées pouvant être lancées comme toute autre exception. Cela a du sens lorsque vous voulez distinguer vos exceptions des autres erreurs lors de l'exécution.

Dans cet exemple, nous allons créer une exception personnalisée pour gérer clairement les problèmes éventuels de l'application tout en analysant une entrée complexe.

Création d'une classe d'exception personnalisée

Pour créer une exception personnalisée, créez une sous-classe d' Exception :

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

Les exceptions personnalisées deviennent très utiles lorsque vous souhaitez fournir des informations supplémentaires au receveur:

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

Maintenant, quand vous catch(ParserException x) vous aurez une sémantique supplémentaire pour affiner la gestion des exceptions.

Les classes personnalisées peuvent implémenter les fonctionnalités suivantes pour prendre en charge des scénarios supplémentaires.

lancer à nouveau

Pendant le processus d'analyse, l'exception d'origine est toujours intéressante. Dans cet exemple, il s'agit d'une FormatException car le code tente d'analyser un morceau de chaîne, qui devrait être un nombre. Dans ce cas, l'exception personnalisée devrait prendre en charge l'inclusion de « InnerException »:

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

sérialisation

Dans certains cas, vos exceptions peuvent avoir à franchir les limites de AppDomain. C'est le cas si votre analyseur s'exécute dans son propre AppDomain pour prendre en charge le rechargement à chaud de nouvelles configurations d'analyseur. Dans Visual Studio, vous pouvez utiliser le modèle Exception pour générer du code comme celui-ci.

[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)
    {}
}

Utiliser l'Exception Parser

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

Vous pouvez également utiliser des exceptions personnalisées pour intercepter et encapsuler des exceptions. De cette façon, de nombreuses erreurs différentes peuvent être converties en un seul type d'erreur plus utile pour l'application:

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

Lorsque vous gérez des exceptions en levant vos propres exceptions personnalisées, vous devez généralement inclure une référence à l'exception d'origine dans la InnerException , comme indiqué ci-dessus.

Problèmes de sécurité

Si exposer la raison de l'exception peut compromettre la sécurité en permettant aux utilisateurs de voir le fonctionnement interne de votre application, il peut être une mauvaise idée d'envelopper l'exception interne. Cela peut s'appliquer si vous créez une bibliothèque de classes qui sera utilisée par d'autres.

Voici comment vous pouvez générer une exception personnalisée sans encapsuler l'exception interne:

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

Conclusion

Lorsque vous déclenchez une exception personnalisée (avec une nouvelle enveloppe ou une nouvelle exception non emballée), vous devez générer une exception significative pour l'appelant. Par exemple, un utilisateur d'une bibliothèque de classes peut ne pas savoir comment cette bibliothèque exécute son travail interne. Les exceptions levées par les dépendances de la bibliothèque de classes ne sont pas significatives. Au contraire, l'utilisateur souhaite une exception qui concerne la manière dont la bibliothèque de classes utilise ces dépendances de manière erronée.

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

Exception Anti-patrons

Exceptions à la déglutition

Il faut toujours relancer l’exception de la manière suivante:

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

Relancer une exception comme ci-dessous masquera l'exception d'origine et perdra la trace de la pile d'origine. On ne devrait jamais faire ça! La trace de la pile avant la capture et la relance sera perdue.

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

Gestion des exceptions de baseball

Il ne faut pas utiliser les exceptions comme substitut aux constructions de contrôle de flux normales comme les instructions if-then et les boucles while. Cet anti-pattern est parfois appelé gestion des exceptions de baseball .

Voici un exemple d'anti-pattern:

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

Voici une meilleure façon de le faire:

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

attraper (Exception)

Il n'y a presque pas (certaines ne disent rien!) De raisons pour intercepter le type d'exception générique dans votre code. Vous ne devriez intercepter que les types d'exception que vous prévoyez, car vous masquez autrement les bogues dans votre code.

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

Mieux vaut faire:

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

Si une autre exception se produit, nous autorisons délibérément l'application à tomber en panne, elle intervient donc directement dans le débogueur et nous pouvons résoudre le problème. Nous ne devons pas expédier un programme où toute autre exception que celle-ci se produit de toute façon, donc ce n'est pas un problème d'avoir un crash.

Ce qui suit est un mauvais exemple, car il utilise des exceptions pour contourner une erreur de programmation. Ce n'est pas pour ça qu'ils sont conçus.

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

Exceptions globales / exceptions multiples d'une méthode

Qui dit que vous ne pouvez pas lancer plusieurs exceptions dans une méthode. Si vous n'avez pas l'habitude de jouer avec AggregateExceptions, vous pouvez être tenté de créer votre propre structure de données pour représenter de nombreuses erreurs. Il y a bien sûr une autre structure de données qui n'est pas une exception serait plus idéale comme les résultats d'une validation. Même si vous jouez avec AggregateExceptions, vous êtes peut-être du côté de la réception et vous les manipulez toujours sans vous rendre compte qu'elles peuvent vous être utiles.

Il est tout à fait plausible de faire exécuter une méthode et même si cela sera un échec dans son ensemble, vous voudrez mettre en évidence plusieurs choses qui ont mal tourné dans les exceptions lancées. A titre d'exemple, ce comportement peut être vu avec le fonctionnement des méthodes Parallel, une tâche divisée en plusieurs threads et un nombre quelconque d'entre elles pouvant générer des exceptions et cela doit être signalé. Voici un exemple stupide de la façon dont vous pourriez en bénéficier:

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

Nidification des exceptions et essayez les blocs de capture.

On peut imbriquer une exception / try bloc catch dans l'autre.

De cette façon, vous pouvez gérer de petits blocs de code capables de fonctionner sans perturber l’ensemble de votre mécanisme.

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
}

Remarque: évitez les exceptions de déglutition lors du lancement sur le bloc catch parent

Les meilleures pratiques

Cheatsheet

FAIRE Ne pas
Contrôle du flux avec des instructions de contrôle Contrôle des flux avec des exceptions
Suivre les exceptions ignorées (absorbées) en se connectant Ignorer l'exception
Répétez l'exception en utilisant throw Re-jeter une exception - throw new ArgumentNullException() ou throw ex
Lancer des exceptions système prédéfinies Jeter des exceptions personnalisées similaires aux exceptions système prédéfinies
Jeter une exception personnalisée / prédéfinie si elle est cruciale pour la logique de l'application Lancer des exceptions personnalisées / prédéfinies pour indiquer un avertissement dans le flux
Catch exceptions que vous souhaitez gérer Attraper toutes les exceptions

NE PAS gérer la logique métier avec des exceptions.

Le contrôle de flux ne doit PAS être effectué par des exceptions. Utilisez plutôt des instructions conditionnelles. Si un contrôle peut être effectué avec l'instruction if-else clairement, n'utilisez pas les exceptions car cela réduit la lisibilité et les performances.

Considérez l'extrait suivant de Mr. Bad Practices:

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

Lorsque l'exécution atteint Console.WriteLine(myObject.ToString()); l'application lancera une exception NullReferenceException. M. Bad Practices s'est rendu compte que myObject était nul et a modifié son extrait pour intercepter et gérer NullReferenceException :

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

Comme l'extrait de myObject précédent ne couvre que la logique d'exception, que dois-je faire si myObject n'est pas nul à ce stade? Où devrais-je couvrir cette partie de la logique? Juste après Console.WriteLine(myObject.ToString()); ? Qu'en est-il après le try...catch block?

Qu'en est-il de Mr. Best Practices? Comment va-t-il gérer ça?

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

M. Best Practices a atteint la même logique avec moins de code et une logique claire et compréhensible.

NE PAS rejeter les exceptions

Relancer les exceptions est coûteux. Cela a un impact négatif sur les performances. Pour le code qui échoue régulièrement, vous pouvez utiliser des modèles de conception pour minimiser les problèmes de performances. Cette rubrique décrit deux modèles de conception utiles lorsque des exceptions peuvent avoir un impact significatif sur les performances.

NE PAS absorber les exceptions sans enregistrement

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

Ne jamais avaler les exceptions. Ignorer les exceptions sauvera ce moment mais créera un chaos pour la maintenabilité plus tard. Lors de la journalisation des exceptions, vous devez toujours consigner l'instance d'exception afin que la trace complète de la pile soit consignée et non uniquement le message d'exception.

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

Ne pas intercepter les exceptions que vous ne pouvez pas gérer

De nombreuses ressources, telles que celle-ci , vous invitent fortement à réfléchir aux raisons pour lesquelles vous attrapez une exception à l'endroit où vous la capturez. Vous ne devriez attraper une exception que si vous pouvez la gérer à cet endroit. Si vous pouvez faire quelque chose pour atténuer le problème, par exemple essayer un autre algorithme, vous connecter à une base de données de sauvegarde, essayer un autre nom de fichier, attendre 30 secondes et réessayer ou avertir un administrateur, vous pouvez détecter l'erreur. S'il n'y a rien que vous puissiez faire de manière plausible et raisonnable, il suffit de "laisser aller" et de laisser l'exception être traitée à un niveau supérieur. Si l'exception est suffisamment catastrophique et qu'il n'y a pas d'autre option raisonnable que le blocage complet du programme en raison de la gravité du problème, laissez-le tomber en panne.

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.

Exception non gérée et thread

AppDomain.UnhandledException Cet événement fournit une notification des exceptions non interceptées. Il permet à l'application de consigner des informations sur l'exception avant que le gestionnaire par défaut du système ne signale l'exception à l'utilisateur et qu'il mette fin à l'application. des actions peuvent être entreprises - telles que la sauvegarde des données du programme pour une récupération ultérieure. Une mise en garde est recommandée, car les données du programme peuvent être corrompues lorsque des exceptions ne sont pas gérées.

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

Application.ThreadException Cet événement permet à votre application Windows Forms de gérer les exceptions non gérées qui se produisent dans les threads Windows Forms. Attachez vos gestionnaires d'événements à l'événement ThreadException pour gérer ces exceptions, ce qui laissera votre application dans un état inconnu. Dans la mesure du possible, les exceptions doivent être gérées par un bloc de gestion des exceptions structuré.

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

Et enfin la gestion des exceptions

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
    }

Lancer une exception

Votre code peut, et devrait souvent, lancer une exception lorsque quelque chose d'inhabituel s'est produit.

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
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow