web-dev-qa-db-fra.com

retour au milieu d'un bloc d'utilisation

Quelque chose comme:

using (IDisposable disposable = GetSomeDisposable())
{
    //.....
    //......
    return Stg();
}

Je crois que ce n'est pas un endroit approprié pour une déclaration de retour, n'est-ce pas?

174
tafa

Comme plusieurs autres l'ont souligné, ce n'est pas un problème.

Le seul cas qui vous causera des problèmes est si vous retournez au milieu d'une instruction using et renvoyez également la variable in using. Mais là encore, cela pourrait aussi vous causer des problèmes même si vous n’êtes pas revenu et conservez simplement une référence à une variable.

using ( var x = new Something() ) { 
  // not a good idea
  return x;
}

Tout aussi mauvais

Something y;
using ( var x = new Something() ) {
  y = x;
}
183
JaredPar

C'est parfaitement bien.

Vous pensez apparemment que

using (IDisposable disposable = GetSomeDisposable())
{
    //.....
    //......
    return Stg();
}

est aveuglément traduit en:

IDisposable disposable = GetSomeDisposable()
//.....
//......
return Stg();
disposable.Dispose();

Ce qui, certes, poserait un problème et rendrait l’instruction using plutôt inutile - c’est la raison pour laquelle pas ce qu’elle fait.

Le compilateur s'assure que l'objet est supprimé avant que le contrôle ne quitte le bloc, quelle que soit la façon dont il quitte le bloc.

125
James Curran

C'est absolument parfait - pas de problème du tout. Pourquoi crois-tu que c'est faux?

Une instruction using est juste un sucre syntaxique pour un bloc try/finally et, comme Grzenio le dit, il est acceptable de revenir d'un bloc try également.

L'expression de retour sera évaluée, puis le bloc finally sera exécuté, puis la méthode retournera.

91
Jon Skeet

Cela fonctionnera parfaitement, comme si vous reveniez au milieu de try{}finally{}

25
Grzenio

C'est totalement acceptable. Une instruction utilisant garantit que l’objet IDisposable sera supprimé quoi qu’il en soit.

De MSDN :

L'instruction using garantit que Dispose est appelé même si une exception se produit pendant que vous appelez des méthodes sur l'objet. Vous pouvez obtenir le même résultat en plaçant l'objet dans un bloc try, puis en appelant Dispose dans un bloc finally; En fait, c'est ainsi que l'instruction using est traduite par le compilateur.

16
mbillard

Le code ci-dessous montre comment fonctionne using:

private class TestClass : IDisposable
{
   private readonly string id;

   public TestClass(string id)
   {
      Console.WriteLine("'{0}' is created.", id);
      this.id = id;
   }

   public void Dispose()
   {
      Console.WriteLine("'{0}' is disposed.", id);
   }

   public override string ToString()
   {
      return id;
   }
}

private static TestClass TestUsingClose()
{
   using (var t1 = new TestClass("t1"))
   {
      using (var t2 = new TestClass("t2"))
      {
         using (var t3 = new TestClass("t3"))
         {
            return new TestClass(String.Format("Created from {0}, {1}, {2}", t1, t2, t3));
         }
      }
   }
}

[TestMethod]
public void Test()
{
   Assert.AreEqual("Created from t1, t2, t3", TestUsingClose().ToString());
}

Sortie:

't1' est créé.
't2' est créé.
't3' est créé.
'Créé à partir de t1, t2, t3' est créé.
't3' est éliminé.
't2' est éliminé.
't1' est éliminé.

Les disposées sont appelées après l'instruction return mais avant la sortie de la fonction.

10
Bertrand