8
votes

C #: équivalent du bloc Python Essayer / Sinon Block

en python, il existe ce code de manipulation d'exception utile:

if (!IsReadOnly)
{
    T newobj;
    try
    {
        newobj = DataPortal.Update<T>(this);

        List<string> keys = new List<string>(BasicProperties.Keys);
        foreach (string key in keys)
        {
            BasicProperties[key] = newobj.BasicProperties[key];
        }
    }
    catch (DataPortalException)
    {
        // TODO: Implement DataPortal.Update<T>() recovery mechanism
    }
}


3 commentaires

J'ai toujours détesté à l'aide d'essayer des blocs de capture à cause de cela. Il n'y a aucun moyen de séparer le code de rupture et n'a pas cassé le code.


Vote à proximité comme duplicata exact: Stackoverflow.com/questions/1177438/c-try-catch-else


Cela pourrait être une duplication, mais cette question n'a jamais été suffisamment répondue. Après avoir lu sur les réponses, j'aime le concept de Daniel Newby le meilleur.


10 Réponses :


0
votes

Vous pouvez faire quelque chose comme ceci:

if (!IsReadOnly)
{
    T newobj = null;
    try
    {
        newobj = DataPortal.Update<T>(this);    
    }
    catch (DataPortalException)
    {
        // TODO: Implement DataPortal.Update<T>() recovery mechanism
    }
    if (newobj != null)
    {
        List<string> keys = new List<string>(BasicProperties.Keys);
        foreach (string key in keys)
        {
            BasicProperties[key] = newobj.BasicProperties[key];
        }
    }
}


0 commentaires

0
votes

Ce serait la déclaration vide comme Hits xxx


0 commentaires

9
votes

Je préférerais voir le reste du code en dehors de l'essai / attraper, il est donc clair que l'exception que vous essayez d'attraper vient de venir de et que vous ne attrapez pas accidentellement une exception que vous n'essayez pas de Catch.

Je pense que l'équivalent le plus proche de la Python Essayez / Catch est d'utiliser une variable booléenne locale à mémoriser si une exception a été lancée ou non. P>

bool success;

try
{
    foo();
    success = true;
}
catch (MyException)
{
    recover();
    success = false;
}

if (success)
{
    bar();
}


5 commentaires

+1 pour la partie "Poignée de l'exception correctement". Si vous ne pouvez pas récupérer à partir de l'exception, vous devriez probablement arrêter de faire ce que vous faites immédiatement. Si vous ne pouvez pas vous empêcher d'arrêter gracieusement, refacteur pour que vous puissiez.


+1, mais je dois demander: comment va-t-il mieux que de mettre l'appel au bar () juste avant la prise?


@David: avec le code que j'ai donné, si la fonction jette une myException, il ne sera pas attrapé mais avec votre suggestion, elle sera prise. La méthode que j'ai montrée plus proche du Essayez: Catch: Sinon: Construire dans ces exceptions soulevées dans le sinon ne sont pas capturés.


J'utilise ce modèle assez souvent et j'initialise généralement succès à false - enregistre moi une ligne de code dans le bloc .


Parfois, il est approprié de pré_do; essayez {do} attraper (erreur) {récupérer} else {do_more}; post_do; . Cela ne signifie pas que l'erreur n'a pas été récupérée ou que le code n'a pas complètement abandonné ce qu'il avait besoin.



2
votes

c # n'a pas un tel concept, vous êtes donc simplement laissé avec trois options,

  • Mettez le code de l'extérieur à l'intérieur de l'essai.
  • Mettez le code de l'autre en dehors du bloc de capture d'essai, utilisez une variable locale pour indiquer le succès ou l'échec, et un bloc IF autour de votre autre code.
  • Mettez le code de l'autre dans le bloc enfin utilisé, utilisez une variable locale pour indiquer le succès ou l'échec, et un numéro de blocage de Block You SIDE.

0 commentaires

2
votes

Il suffit de mettre votre bloc "autre" avant em> la prise. Ensuite, il n'exécutera que si l'exécution de code n'atteint que le point:

try
{
    fee();
    fi();
    foe();
    fum();

    /// put your "else" stuff here. 
    /// It will only be executed if fee-fi-foe-fum did not fail.
}
catch(Exception e)
{
    // handle exception
}


6 commentaires

La différence est qu'il y a 1 ligne qui devrait lancer une exception et que vous vous attendez à ce que cela puisse arriver et l'attraper. Si une ligne différente a jeté l'exception qui pourrait être quelque chose que vous ne voulez pas attraper, car cela peut indiquer un bogue réel.


@ Davy8 Dans ce cas, vous devez soit être a) Attraper uniquement le type d'exception spécifique que vous attendez, ou b) placez le code que vous ne vous attendez pas à générer une exception à l'extérieur de cet essai. .catch Block. Dans tous les cas, vous devriez toujours attraper des exceptions qui se produisent afin que vous puissiez échouer gracieusement.


Il est proche, mais ce n'est pas assez équivalent. Si c'est juste à l'extérieur de l'essai / attrape, il s'exécutera, que la première section a jeté une exception, mais elle ne devrait exécuter que lorsque la première partie n'a pas lancé. Il est possible que le même type d'exception puisse être jeté, de sorte que la capture d'une exception spécifique est une amélioration, mais n'est pas exactement la même chose.


@DavidLively: Vous ne devez pas échouer gracieusement d'un bug qui ne devrait pas exister. Si une sorte de cohérence doit être maintenue, le code d'appel devrait s'assurer que et signaler l'erreur.


@Noctiskkytower par opposition aux bugs que devrait-il exister ? Je conviens que l'utilisation d'exceptions pour le contrôle de flux est mauvaise. Si, par exemple, vous expédiez une bibliothèque qui doit masquer l'exception réelle, laissant la journalisation jusqu'à l'appelant peut être inacceptable. Il y a des circonstances - parler à un périphérique externe. Par exemple, où ce type de problème ne peut pas être résolu par la conception.


Si vous aimez demander le pardon plutôt que l'autorisation, une exception ne signifie pas nécessairement un bug. Je m'excuse pour mon libellé. Certaines échecs ou exceptions peuvent être corrects tandis que d'autres sont clairement une erreur ou un bogue dans le programme. La réponse de Daniel Newby peut ne pas être préférée, mais j'ai aimé la façon dont elle est traduite de Python à C #.



2
votes

Permettez-moi de répéter une idée d'un Question similaire Stackoverflow . Vous ne pouvez pas faire cela directement, mais vous pouvez écrire une méthode qui encapsule le comportement dont vous avez besoin. Regardez la question initiale pour voir comment implémenter la méthode (si vous n'êtes pas familier avec Lambda Expressions et Func Délégués). L'utilisation pourrait ressembler à ceci: xxx


0 commentaires

8
votes

Solution barbare: Créez une classe d'autre dérivée de l'exception, lancez une instance de celui-ci à la fin du bloc d'essai et utilisez attraper (autre) {...} pour gérer les autres trucs .

Je me sens si sale.


2 commentaires

Je ne sais pas quoi faire ici - cela demande A -1 vote, mais je suis assez amusé pour hésiter à le faire.


Sinon à Python n'atteignent pas toutes les autres exceptions. Sinon, est seulement couru quand aucune exception n'est présente.



3
votes

Ceci pourrait être évité pour être évité mais ne peut pas goto (notez que je n'ai presque aucune connaissance de C #, donc je n'ai aucune idée si cela fonctionne).

Qu'en est-il de quelque chose comme P>

try 
{ 
...
} 
catch(Exception ex) 
{ 
...
goto Jump_past_tryelse
} 
...//Code to execute if the try block DID NOT fail

Jump_past_tryelse:
...


3 commentaires

Je vous ai presque donné un +1 simplement pour offrir tout le pub avec votre «goto»!


"Offrir tout le pub" ==?


@ Romana.Taycher 8 ans plus tard, googling "offrant tout le pub" rendement exactement 1 résultat de recherche: cette page. Je suppose que nous ne saurons jamais ...



0
votes
if (!IsReadOnly)
        {
            T newobj;
            bool Done;
            try
            {
                newobj = DataPortal.Update<T>(this);
                List<string> keys = new List<string>(BasicProperties.Keys);
                foreach (string key in keys)
                {
                    BasicProperties[key] = newobj.BasicProperties[key];
                }
                Done = true;
            }
            catch (DataPortalException)
            {
                // TODO: Implement DataPortal.Update<T>() recovery mechanism
                Done = false;
            }
            finally
            {
                if (newobj != null && Done == false)
                {
                    List<string> keys = new List<string>(BasicProperties.Keys);
                    foreach (string key in keys)
                    {
                        BasicProperties[key] = newobj.BasicProperties[key];
                    }
                }
            }
        }

0 commentaires

1
votes

avec c # version 7, Vous pouvez utiliser fonctions locales pour imiter ce comportement:

Exemple 1: (puisque c # version 7 ) xxx

Si vous préférez Syntaxe Lambda, Vous pouvez également déclarer une méthode d'exécution xxx

qui doit seulement être là une fois dans votre code, puis utilisez le modèle pour les méthodes anonymes comme suit

EXEMPLE 2: (anciennes versions C # et c # Version 7) xxx

où vous devez entendre un code dans un contexte sûr.

Essayez-le dans dotnetfiddle


Notes:

  • Dans les deux exemples, un contexte de fonction est créé afin que nous puissions utiliser retour; pour quitter l'erreur.
  • Vous pouvez trouver un motif similaire comme celui utilisé dans Exemple 2 en JavaScript: Auto-invoquant des fonctions anonymes (par exemple, JQuery les utilise). Parce que dans C #, vous ne pouvez pas vous auto-invoquer, la méthode de l'assistance exécuter est utilisée.
  • car exécuter ne doit pas nécessairement être une fonction locale, Exemple 2 fonctionne avec des versions C # plus anciennes, ainsi que

0 commentaires