web-dev-qa-db-fra.com

Est-ce une bonne approche pour appeler return inside à l'aide de l'instruction {}?

Je veux juste savoir si c'est une approche sûre/bonne d'appeler return à l'intérieur d'un bloc using.

Par exemple.

using(var scope = new TransactionScope())
{
  // my core logic
  return true; // if condition met else
  return false;
  scope.Complete();
}

Nous savons que la dernière accolade la plus frisée dispose() sera annulée. Mais ce sera dans le cas ci-dessus, puisque return saute le contrôle hors de la portée donnée (AFAIK) ...

  1. Est-ce que ma scope.Complete() est appelée?
  2. Et donc pour la méthode dispose() de l'oscilloscope.
78
user240141

Il est parfaitement sûr d'appeler return à l'intérieur de votre bloc using, car un bloc using n'est qu'un bloc try/finally.

Dans votre exemple ci-dessus après return true, la portée sera supprimée et la valeur retournée. return false Et scope.Complete()pas seront appelés. Dispose sera cependant appelé car il réside dans le bloc finally.

Votre code est essentiellement le même que celui-ci (si cela le rend plus facile à comprendre):

var scope = new TransactionScope())
try
{
  // my core logic
  return true; // if condition met else
  return false;
  scope.Complete();
}
finally
{
  if( scope != null) 
    ((IDisposable)scope).Dispose();
}

Veuillez noter que votre transaction sera jamais validée car il n'y a aucun moyen d'accéder à scope.Complete() pour valider la transaction.

120
Øyvind Bråthen

C'est très bien - les clauses finally (ce que fait l'accolade fermante de la clause using sous le capot) sont toujours exécutées lorsque la portée est laissée, peu importe comment.

Cependant, cela n'est vrai que pour les instructions qui se trouvent dans le bloc finally (qui ne peuvent pas être définies explicitement lors de l'utilisation de using). Par conséquent, dans votre exemple, scope.Complete() ne serait jamais appelé (je m'attends cependant à ce que le compilateur vous avertisse du code inaccessible).

6
Lucero

scope.Complete doit définitivement être appelé avant return. Le compilateur affichera un avertissement et ce code ne sera jamais appelé.

Concernant return lui-même - oui, il est sûr de l'appeler à l'intérieur de l'instruction using. L'utilisation est traduite pour essayer de bloquer le bloc en arrière-plan et enfin le bloc doit certainement être exécuté.

2
Tony Kh

En général, c'est une bonne approche. Mais dans votre cas, si vous revenez avant d'appeler la scope.Complete(), cela supprimera simplement le TransactionScope. Dépend de votre conception.

Ainsi, dans cet exemple, Complete () n'est pas appelé et la portée est supprimée, en supposant qu'elle hérite de l'interface IDisposable.

2
M. Mennan Kara

Pour vous assurer que la scope.Complete() sera appelée, enveloppez-la avec try/finally. Le dispose est appelé parce que vous l'avez enveloppé avec le using qui est une alternative try/finally bloquer.

using(var scope = new TransactionScope())
{
  try
  {
  // my core logic
  return true; // if condition met else
  return false;
  }
  finally
  {
   scope.Complete();
  }
}
1
Aristos

Dans l'exemple que vous avez fourni, il y a un problème; scope.Complete() n'est jamais appelée. Deuxièmement, il n'est pas recommandé d'utiliser l'instruction return dans les instructions using. Référez-vous à ce qui suit:

using(var scope = new TransactionScope())
{
    //have some logic here
    return scope;      
}

Dans cet exemple simple, le fait est que; la valeur de scope sera nulle lorsque l'utilisation de l'instruction est terminée.

Il est donc préférable de ne pas retourner à l'intérieur en utilisant des instructions.

1
daryal

Dans cet exemple, scope.Complete () ne s'exécutera jamais. Cependant, la commande de retour nettoiera tout ce qui est affecté sur la pile. Le GC prendra soin de tout ce qui n'est pas référencé. Donc, à moins qu'il n'y ait un objet qui ne peut pas être ramassé par le GC, il n'y a pas de problème.

0
ThunderGr