Является ли хороший подход к вызову return внутри с помощью выражения {}?

Я просто хочу знать, безопасно ли/хорошо подходит для вызова return внутри блока using.

Например,

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

Мы знаем, что в последней самой фигурной скобке dispose() будет отменено. Но что будет в вышеуказанном случае, так как return перескакивает контроль из данной области (AFAIK)...

  • Вызывается ли мой scope.Complete()?
  • И так для метода scope dispose().
+67
02 авг. '12 в 11:59
источник поделиться
7 ответов

Совершенно безопасно вызывать return внутри вашего блока using, поскольку используемый блок - это всего лишь блок try/finally.

В приведенном выше примере после возврата true область действия будет удалена и возвращаемое значение. return false, а scope.Complete() вызывается не. Dispose однако будет вызываться независимо от того, что он находится внутри блока finally.

Ваш код по существу такой же, как и этот (если это проще понять):

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

Имейте в виду, что ваша транзакция будет никогда зафиксирована, так как нет возможности добраться до scope.Complete(), чтобы зафиксировать транзакцию.

+104
02 авг. '12 в 12:02
источник

Это прекрасное - finally предложения (это то, что закрывает фигурные скобки из предложения using делает под капотом) всегда выполняется, когда область видимости остается вне зависимости от того, как.

Однако это справедливо только для операторов, которые находятся в блоке finally (который не может быть явно установлен при использовании using). Поэтому в вашем примере scope.Complete() никогда не будет вызван (я ожидаю, что компилятор предупредит вас о недоступном коде).

+7
02 авг. '12 в 12:02
источник

В целом, это хороший подход. Но в вашем случае, если вы вернетесь, прежде чем называть scope.Complete(), он просто уничтожит TransactionScope. Зависит от вашего дизайна.

Итак, в этом примере функция Complete() не вызывается и область видимости располагается, предполагая, что она наследует интерфейс IDisposable.

+3
02 авг. '12 в 12:03
источник

scope. Полноценный должен быть определен до return. Компилятор отобразит предупреждение, и этот код никогда не будет вызываться.

Что касается самого return - да, его можно вызвать внутри оператора using. Использование переведено в блок try-finally за сценой, и, наконец, блок, безусловно, выполняется.

+3
02 авг. '12 в 12:07
источник

Чтобы убедиться, что будет вызываться scope.Complete(), оберните его try/finally. Вызов dispose вызывается, потому что вы завернули его с помощью using, который является альтернативным блоком try/finally.

using(var scope = new TransactionScope())
{
  try
  {
  // my core logic
  return true; // if condition met else
  return false;
  }
  finally
  {
   scope.Complete();
  }
}
+2
02 авг. '12 в 12:04
источник

В примере, который вы указали, возникает проблема; scope.Complete() никогда не вызывается. Во-вторых, не рекомендуется использовать инструкцию return внутри операторов using. Обратитесь к следующему:

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

В этом простом примере дело в том, что; значение scope будет равно null, когда использование инструкции завершено.

Так что лучше не возвращаться внутрь с помощью утверждений.

+2
02 авг. '12 в 12:09
источник

В этом примере scope.Complete() никогда не будет выполняться. Однако команда return очистит все, что назначено в стеке. GC будет заботиться обо всем, что не указано. Таким образом, если нет объекта, который не может быть захвачен GC, нет проблем.

+1
02 авг. '12 в 12:07
источник

Посмотрите другие вопросы по меткам или Задайте вопрос