La différence entre paramètre moins de prise de re-lancer et ne pas faire quoi que ce soit?

StackOverflow https://stackoverflow.com/questions/717489

  •  23-08-2019
  •  | 
  •  

Question

Supposons que j'ai les deux classes suivantes dans deux ensembles différents:

//in assembly A
public class TypeA {
   // Constructor omitted
   public void MethodA
   {
     try {
       //do something
     }
     catch {
        throw;
     }
   }
}
//in assembly B
public class TypeB {
   public void MethodB
   {
     try {
       TypeA a = new TypeA();
       a.MethodA();
     }
     catch (Exception e)
       //Handle exception
     }
   }
}

Dans ce cas, le try-catch dans METHODA juste l'exception élève l'mais ne gère pas vraiment. Est-il un avantage à utiliser try-catch tout en METHODA? Autrement dit, est-il une différence entre ce type de bloc try-catch et de ne pas utiliser du tout?

Était-ce utile?

La solution

Dans votre exemple, il n'y a aucun avantage à ce sujet. Mais il y a des cas où il est souhaitable juste une bulle d'exception spécifique.

    public void Foo()
    {
        try
        {
            // Some service adapter code

            // A call to the service
        }
        catch (ServiceBoundaryException)
        {
            throw;
        }
        catch (Exception ex)
        {
            throw new AdapterBoundaryException("some message", ex);
        }
    }

Cela vous permet d'identifier facilement de limite une exception a eu lieu. Dans ce cas, vous devez vous assurer que vos exceptions aux limites ne sont jetés pour le code spécifique à la frontière.

Autres conseils

Oui, il y a une différence. Lorsque vous attrapez une exception, .NET suppose que vous allez gérer en quelque sorte, la pile est dévidé jusqu'à la fonction qui fait la prise.

Si vous ne l'attrape pas finira comme une exception non gérée, qui invoquera une sorte de diagnostic (comme un débogueur ou un enregistreur d'exception), la pile complète et son état au moment de l'échec réel sera disponible pour l'inspection.

Donc, si vous attrapez puis re-jeter une exception non gérée ailleurs vous voler l'outil de diagnostic de l'information vraiment utile sur ce qui est arrivé.

Pris tel quel, la première option semble être une mauvaise (ou devrait-il être « inutile »?) Idée. Cependant, il est rarement fait de cette façon. Des exceptions sont relancées à l'intérieur d'un bloc Catch généralement sous deux conditions:

a. Vous voulez vérifier l'exception générée pour les données et la bulle sous condition qu'il la pile.

try 
{
  //do something
}
catch (Exception ex)
{
  //Check ex for certain conditions.
  if (ex.Message = "Something bad")
    throw ex;
  else
    //Handle the exception here itself.
}

b. Une condition inacceptable est produite dans un composant et cette information doit être communiquée au code d'appel (généralement en ajoutant d'autres informations utiles ou l'envelopper dans une autre exception de type tout à fait).

try 
{
  //do something
}
catch (StackOverflowException ex)
{
    //Bubble up the exception to calling code 
    //by wrapping it up in a custom exception.
    throw new MyEuphemisticException(ex, "Something not-so-good just happened!");
}

Juste rethrowing n'a pas de sens -. C'est la même chose que si vous ne faites rien

Cependant, il devient utile lorsque vous faites quelque chose en fait - chose la plus courante consiste à connecter l'exception. Vous pouvez également changer d'état de votre classe, peu importe.

Avec le code de la façon dont vous l'avez écrit pour METHODA, il n'y a pas de différence. Tout ce qu'il va faire est de manger des cycles de processeur. Cependant, il peut y avoir un avantage à l'écriture de code de cette façon s'il y a une ressource que vous devez libérer. Par exemple

Resource r = GetSomeResource();
try {
  // Do Something
} catch { 
  FreeSomeResource();
  throw;
}
FreeSomeResource();

Cependant, il n'y a pas de véritable point ce faire de cette façon. Il serait beaucoup mieux simplement utiliser un bloc finally à la place.

Ne faites jamais l'option A. Comme Anton dit, il mange la trace de la pile. L'exemple de JaredPar mange aussi le stacktrace. Une meilleure solution serait:

SomeType* pValue = GetValue();
try {
  // Do Something
} finally {
  delete pValue;
}

Si vous avez quelque chose en C # qui doit être libéré, par exemple un FileStream vous avez les deux choix suivants:

FileStream stream;
try
{
  stream = new FileStream("C:\\afile.txt");
  // do something with the stream
}
finally
{
  // Will always close the stream, even if there are an exception
  stream.Close(); 
}

Ou plus proprement:

using (FileStream stream = new FileStream("c:\\afile.txt"))
{
  // do something with the stream
}

instruction Using vous débarrasserez (et fermer) le flux lorsque vous avez terminé ou lorsqu'une exception est fermée.

Lorsque vous attraper et lancer, il vous permet de définir un point d'arrêt sur la ligne de throw.

exceptions Re-PROJECTION peuvent être utilisées pour encapsuler dans exception générique comme ... considérer l'exemple suivant.

public class XmlException: Exception{
   ....
} 

public class XmlParser{
   public void Parse()
   {
      try{
          ....
      }
      catch(IOException ex)
      {
         throw new XmlException("IO Error while Parsing", ex );
      }
   }
}

Cela donne avantage sur les exceptions de classement par catégorie. Voici comment les gestionnaires de fichiers ASPX et beaucoup d'autres codes du système ne encapsulation d'exception qui détermine leur chemin jusqu'à la pile et leur flux de la logique.

L'ensemble A - essayer catch - bloc ne fait pas de sens pour moi. Je crois que si vous n'allez gérer l'exception, alors pourquoi attrapez-vous ces exceptions .. Il serait jeté de toute façon au niveau suivant.

Mais, si vous créez une API de couche intermédiaire ou quelque chose comme ça et la manipulation d'une exception (et manger donc l'exception) dans cette couche n'a pas de sens, alors vous pouvez jeter votre propre couche ApplicationException. Mais rethrowing certainement la même exception n'a pas de sens.

Comme les classes sont en 2 assemblées différentes, vous voudrez peut-o simplement attraper l'exception pour la connexion, puis de le renvoyer vers l'appelant, afin qu'il puisse gérer la façon dont il le juge opportun. A deux pas au lieu d'un ex throw conservera des informations contextuelles sur l'endroit où l'exception est née. Cela peut se révéler utile lorsque votre assemblage est une API / cadre où en vous ne devriez jamais avaler des exceptions à moins que son sens de le faire, mais utile néanmoins en difficulté le tir si elle est connecté par exemple à la EventLog.

Vous pouvez utiliser try {} catch (ex) {} bloc dans la méthode A seulement si vous pouvez intercepter l'exception spécifique qui peut être manipulé dans METHODA () (par exemple: l'exploitation forestière).

Une autre option est la chaîne à l'exception en utilisant la propriété InnerException et le transmettre à l'appelant. Cette idée ne tue pas la trace de la pile.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top