Как использовать конструкцию try-finally в C #?

Мы видели много вопросов о try-catch-finally и try-finally конструкциях на этом форуме.

Количество ответов увеличивает количество вопросов, поэтому у меня тоже мало.

Вот ссылка на объяснение Microsoft. попробуй наконец строительство. Я это уже читал!

В следующей статье пишет:

В пределах обработанного исключения гарантированно запускается связанный блок finally. Однако, если исключение не обрабатывается, выполнение блока finally зависит от того, как запускается операция очистки исключения. Это, в свою очередь, зависит от того, как настроен ваш компьютер.

  1. Правильно ли я понимаю, что в try-catch-finally конструкция finally всегда будет выполняться? (Исключая Environment.FastFail())

    Я читал о StackOverFlowException (этот finally блок в данном случае не выполняется) на этом форуме, но когда я throw это, блок finally выполняется. Так что насчет StackOverFlowException?

  2. Почему блок finally не вызывается? (В коде ниже)?

  3. В каких случаях мы обычно используем try-finally?

  4. От какого ПК зависит установка блока finally?


using System;
namespace ConsoleApplication1
{
class Program
    {
    static void Main(string[] args)
        {
            try
            {
                throw  new Exception(); 
            }                              
            finally
            {
                Console.WriteLine("finally");
                Console.ReadKey();
            }
        }
    }
}    

person Oleg Yanytskii    schedule 02.01.2019    source источник
comment
Это 4,5 вопроса; это, вероятно, будет закрыто как слишком широкое.   -  person Roger Lipscombe    schedule 02.01.2019
comment
обычно ваш finally всегда запускается, поэтому вы можете удалить свои объекты и закрыть все утечки памяти, если они созданы. На вопрос, как настроен ваш компьютер, я не знаю ...   -  person HomeForce    schedule 02.01.2019
comment
этот форум не хочет быть форумом.   -  person bommelding    schedule 02.01.2019
comment
Этот блок finally должен запуститься. Вы ведь знаете, как продолжить работу в отладчике, верно?   -  person bommelding    schedule 02.01.2019


Ответы (3)


  1. Да, в большинстве случаев блок finally всегда будет выполняться, если вы не прервете выполнение с помощью чего-то вроде Environment.Exit(0) или Application.Exit() (например, Common Man, упомянутый в его ответе).

    В случае StackOverFlowException и других сбоев глубокого приложения он не может работать, поскольку, когда стек заполнен, в этом потоке не остается памяти для выполнения любой нормальной операции. Таким образом, когда вы сами генерируете исключение, реального полного стека нет, и приложение может продолжать работу.

  2. Блок finally не вызывается в отладчике, поскольку отладчик немедленно закрывается, если есть необработанное исключение на верхнем уровне, поскольку нет обработчика исключений верхнего уровня. См. этот ответ для более подробного объяснения. Если вы запустите приложение без прикрепленного отладчика, будет вызван блок finally - спасибо bommelding за это выяснение.

  3. Вы используете блоки finally каждый раз, когда вам нужно правильно очистить. См. этот ответ для более подробного объяснения.

  4. Это сложный вопрос, я думаю, он предназначен для описания эффектов от настроек ПК, таких как антивирусные сканеры, завершающие программы, когда они пытаются создать переполнение буфера или аналогичную, возможно, критическую ситуацию. Аналогичным образом выполнение блоков finally может быть предотвращено с помощью предотвращения выполнения данных или других функций безопасности.

person Compufreak    schedule 02.01.2019
comment
re 2: он обязательно должен работать. - person bommelding; 02.01.2019
comment
@bommelding Сначала я тоже так подумал, но нет, он не запускается - посмотрите связанный ответ и попробуйте сами. Не запускается. - person Compufreak; 02.01.2019
comment
Хорошо, это не работает в отладчике, беда. Нажмите Ctrl + F5, а затем закройте программу. Вы увидите наконец. - person bommelding; 02.01.2019
comment
Вы правы, это интересно. Я соответствующим образом отредактирую свой ответ. - person Compufreak; 02.01.2019

1. правильно ли я понимаю, что в конструкции try-catch-finally всегда будет выполняться конструкция finally? (Исключая Environment.FastFail())

Блок finally не будет вызываться после возврата в нескольких уникальных сценариях: если первым вызывается System.exit() или если виртуальная машина аварийно завершает работу.

2. Почему finally блок не вызывается? (В коде ниже)?

Прочтите здесь: Можно ли прервать / приостановить блок finally?

  1. В каких случаях мы обычно используем try-finally?

try{} finally{} следует использовать в случаях, когда вы не можете обработать исключение, но требуются для очистки ресурсов.

Или всегда лучше показать что-то и корректно завершить работу после того, как в нашей программе произошло какое-то исключительное исключение.

person Vishwa Ratna    schedule 02.01.2019

1 - Это зависит от обстоятельств. Идея использования блока finally состоит в том, чтобы очистить ресурсы, выделенные в блоке try. Даже если в блоке try возникает исключение, вы можете запустить код в блоке finally. Однако блок finally гарантированно запускается в обработанном исключении. Если исключение не обрабатывается, выполнение finally зависит от того, как запускается операция очистки исключения.

2 - Ваш finally не вызывается, так как исключение не обрабатывается. В документации Microsoft говорится: «Обычно, когда необработанное исключение завершает приложение, независимо от того, запущен ли блок finally или нет, не имеет значения. Однако, если у вас есть операторы в блоке finally, который должен выполняться даже в этой ситуации, одним из решений является добавление блок catch для оператора try-finally ". Сравните примеры на https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/try-finally, чтобы увидеть разницу между обработанным и необработанным исключением.

Подробнее читайте в этом вопросе Зачем использовать finally на C #?

Источники https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/try-finally https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/try-catch-finally

person iikkoo    schedule 02.01.2019