Нет - на уровне IL вы не можете вернуться изнутри блока с обработкой исключений. По сути, он хранит его в переменной и возвращает потом
то есть похоже на:
int tmp;
try {
tmp = ...
} finally {
...
}
return tmp;
например (с помощью отражателя):
static int Test() {
try {
return SomeNumber();
} finally {
Foo();
}
}
компилируется в:
.method private hidebysig static int32 Test() cil managed
{
.maxstack 1
.locals init (
[0] int32 CS$1$0000)
L_0000: call int32 Program::SomeNumber()
L_0005: stloc.0
L_0006: leave.s L_000e
L_0008: call void Program::Foo()
L_000d: endfinally
L_000e: ldloc.0
L_000f: ret
.try L_0000 to L_0008 finally handler L_0008 to L_000e
}
Это в основном объявляет локальную переменную ( CS$1$0000
), помещает значение в переменную (внутри обработанного блока), затем после выхода из блока загружает переменную, а затем возвращает ее. Отражатель отображает это как:
private static int Test()
{
int CS$1$0000;
try
{
CS$1$0000 = SomeNumber();
}
finally
{
Foo();
}
return CS$1$0000;
}
Оператор finally выполняется, но на возвращаемое значение это не влияет. Порядок исполнения:
Вот короткая программа для демонстрации:
Это печатает «try» (потому что это то, что возвращается), а затем «finally», потому что это новое значение x.
Конечно, если мы возвращаем ссылку на изменяемый объект (например, StringBuilder), то любые изменения, внесенные в объект в блоке finally, будут видны при возврате - это не повлияло на само возвращаемое значение (которое является просто ссылка).
источник
return
оператора, и это значение будет возвращено. Выражение не оценивается, так как контроль покидает метод.Предложение finally выполняется после оператора return, но до фактического возврата из функции. Я думаю, это не имеет ничего общего с безопасностью потоков. Это не хак - гарантированно всегда будет выполняться finally, независимо от того, что вы делаете в блоке try или блоке catch.
источник
Добавляя к ответам, данным Марком Гравеллом и Джоном Скитом, важно отметить, что объекты и другие ссылочные типы ведут себя аналогично при возврате, но имеют некоторые различия.
Возвращаемое «Что» следует той же логике, что и простые типы:
Возвращаемая ссылка уже была оценена до того, как локальной переменной была назначена новая ссылка в блоке finally.
Исполнение по сути:
Разница в том, что все еще можно изменить изменяемые типы, используя свойства / методы объекта, что может привести к неожиданному поведению, если вы не будете осторожны.
Второе, что следует учитывать при использовании try-return-finally, это то, что параметры, передаваемые «по ссылке», все еще можно изменить после возврата. Только возвращаемое значение было оценено и сохранено во временной переменной, ожидающей возврата, все остальные переменные по-прежнему модифицируются обычным способом. Контракт выходного параметра может даже остаться невыполненным до тех пор, пока не будет окончательно заблокирован этот путь.
Как и любая другая конструкция потока, «try-return-finally» имеет свое место и может обеспечить более чистый вид кода, чем написание структуры, в которую он фактически компилируется. Но это нужно использовать осторожно, чтобы избежать ошибок Гоча.
источник
Если
x
это локальная переменная, я не вижу смысла, так какx
в любом случае будет эффективно установлено значение NULL, когда метод завершается, а значение возвращаемого значения не равно NULL (так как оно было помещено в регистр до вызова setx
к нулю).Я могу видеть, как это происходит, только если вы хотите гарантировать изменение значения поля при возврате (и после определения возвращаемого значения).
источник