Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.67/64: Рейтинг темы: голосов - 64, средняя оценка - 4.67
быдлокодер
 Аватар для kravam
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,705

Переменная, объявленная в блоке Try - Catch видна не для всего метода

25.12.2012, 23:51. Показов 12966. Ответов 21
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
    class Program
    {
        static void Main()
        {
            BinaryWriter dataOut;
 
            try
            {
                //вот здесь переменной dataOut присваивается значение
                dataOut = new BinaryWriter(new FileStream("testdata", FileMode.Create));
            }
            catch (IOException exc)
            {
            }
            finally
            {
               //вот здесь якобы ошибка 
               dataOut.Close();
            }
        }
    }
ЧЯДНТ?
Спасибо, кто откликнется.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
25.12.2012, 23:51
Ответы с готовыми решениями:

Try-Catch: чтобы падение в одной строке не приводило к падению всего метода
Как лучше реализовать, чтоб код выполнился весь и падение в одной строке не приводило к падению всего метода? private void Met() ...

Не видна переменная, объявленная в main
Пишет, что переменная numOne не объявлена, хотя я ее объявил в main. #include <stdio.h> void plus(void); void minus(void); void...

Не видна переменная, объявленная в Form1
Здравствуйте. Есть Form1 и класс Objects: public partial class Form1 : Form { public const int MX = 20; ...

21
27 / 27 / 12
Регистрация: 11.11.2009
Сообщений: 86
26.12.2012, 00:46
Если твой try не выполнится, dataOut не присвоено значение, а в finally ты пытаешься закрыть dataOut, а закрывать то нечего.
0
быдлокодер
 Аватар для kravam
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,705
26.12.2012, 02:11  [ТС]
Очень может быть, да только вот беда, эти соображения здесь не срабатывают:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
 
namespace Ch10Ex01
{
    class p
    {
        static void Main()
        {
            BinaryWriter dataOut;
            try
            {
                dataOut = new
                BinaryWriter(new FileStream("testdata", FileMode.Create));
 
            }
            catch (IOException exc)
            {
                //Вот это добавлено
                return;  
            }
 
            //И добавлен этот декоративный блок
            try
            {
            }
            catch (IOException exc)
            {
            }
 
            finally
            {
                dataOut.Close();
            }
        }
    }
}
Теперь всё компилится, а ситуация та же самая, относительно того, что закрывать будет просто-напросто нечего!
0
27 / 27 / 12
Регистрация: 11.11.2009
Сообщений: 86
26.12.2012, 02:19
Почему же ? try здесь выполнилнится полюбому и значит значение dataOut присвоется, а по этому
C#
1
 dataOut.Close();
мы можем закрыть
0
быдлокодер
 Аватар для kravam
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,705
26.12.2012, 02:30  [ТС]
Цитата Сообщение от МихаилМ Посмотреть сообщение
try здесь выполнилнится полюбому и значит значение dataOut присвоется, а по этому
С какой стати?
Вот try из первого поста:
C#
1
2
3
4
           try
            {
                dataOut = new BinaryWriter(new FileStream("testdata", FileMode.Create));
            }
а вот из второго
C#
1
2
3
4
           try
            {
                dataOut = new BinaryWriter(new FileStream("testdata", FileMode.Create));
            }
одно не выполняется, а второе выполняется. Как говорится, найди семь отличий.
0
27 / 27 / 12
Регистрация: 11.11.2009
Сообщений: 86
26.12.2012, 02:44
Второй раз фигню написал, так как плохо посмотрел что к чему.
Все переменные в с# должны быть инициализированы при работе с ними
поэтому, в первом случае где 1 try, выдается ошибка, вдруг try не выполнится, а в finally будет закрываться не инициализированая переменная(хоть dataOut можно и закрыть), не делали исключений в языке.
Второй try работает так как dataOut можно закрывать.
0
быдлокодер
 Аватар для kravam
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,705
26.12.2012, 03:09  [ТС]
Всё равно не понятно. В первом примере не компилит потому, что dataOut неинициализирована, а во втором компилит не потому, что dataOut ИНИЦИАЛИЗИРОВАНА, а потому, что оказывается есть второй блок try

Так как-нибудь надо нам определиться вместе с компилятором.
Либо мы смотрим на инициализацию переменной и в зависимости от этого компилим или нет

Либо смотрим на наличие блока try и в зависимости от этого компилим или нет

А то в одном коде у нас так, в другом эдак.

Ничё нет в этом мире постоянного!
0
Эксперт Java
 Аватар для turbanoff
4094 / 3828 / 745
Регистрация: 18.05.2010
Сообщений: 9,331
Записей в блоге: 12
26.12.2012, 07:27
Цитата Сообщение от kravam Посмотреть сообщение
Либо мы смотрим на инициализацию переменной и в зависимости от этого компилим или нет
Либо смотрим на наличие блока try и в зависимости от этого компилим или нет
Смотрим все возможные варианты развития событий - и от этого, компилим или нет.
Во втором случае вариантов 2:
1. проходим успешно 1-й блок try -> попадаем в finally второго блока
2. вылетает ошибка в 1-м блоке try -> попадаем в catch первого блока -> return

В обоих случаях можно быть точно уверенным, что если попадем в finally второго блока - то переменная dataOut, будет точно инициализирована.
1
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
26.12.2012, 08:16
Ну или так:
C#
1
2
3
4
BinaryWriter writer = null;
try { writer = ... }
catch (IOException) {}
finally { if (writer != null) writer.Close(); }
Или даже так:
C#
1
2
3
using (var writer = ...)
{
}
0
быдлокодер
 Аватар для kravam
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,705
26.12.2012, 14:18  [ТС]
Цитата Сообщение от turbanoff Посмотреть сообщение
Смотрим все возможные варианты развития событий - и от этого, компилим или нет.
если бы оно было так, я бы и сам догадался. Но оно не так!
........................................ ................

Вот вы написали: (жирным я выделил заменённые слова, ибо речь шла о двух блоках trу, а у меня один)

1. проходим успешно 1-й блок try -> попадаем в finally первого блока
2. вылетает ошибка в 1-м блоке try -> попадаем в catch первого блока -> return
В обоих случаях можно быть точно уверенным, что если попадем в finally первого блока - то переменная dataOut, будет точно инициализирована.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
 
namespace Ch10Ex01
{
    class p
    {
        static void Main()
        {
            BinaryWriter dataOut;
            try
            {
                dataOut = new
                BinaryWriter(new FileStream("testdata", FileMode.Create));
 
            }
            catch (IOException exc)
            {
                //Вот это добавлено
                return;
            }
 
            finally
            {
                dataOut.Close();
            }
        }
    }
}
всё так, только компилятор не согласен с нами. Он видит какой-то третий вариант, при котором:

мы попадаем в finally и dataOut оказывается неинициализирована

и потому не компилит... Что ж за вариант-то такой, не подскажите?
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
26.12.2012, 14:22
Цитата Сообщение от kravam Посмотреть сообщение
В обоих случаях можно быть точно уверенным, что если попадем в finally первого блока - то переменная dataOut, будет точно инициализирована.
С чего это вдруг?
FileStream выбрасывает исключение по какой-то причине, объект не создается, переменная остается не проинициализирована, вы сразу же переходите в блок catch, а оттуда в finally.

Об этом варианте вам и сообщает компилятор.
0
быдлокодер
 Аватар для kravam
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,705
26.12.2012, 14:29  [ТС]
Цитата Сообщение от kolorotur Посмотреть сообщение
вы сразу же переходите в блок catch, а оттуда в finally
Нет. Внимательнее:
C#
1
2
3
4
5
catch (IOException exc)
            {
                //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                return;
            }
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
26.12.2012, 14:34
Цитата Сообщение от kravam Посмотреть сообщение
Нет. Внимательнее:
Я внимательный.
Блок finally на то и finally, что выполняется в любом случае, не приводящем к принудительному завершению приложения.
В вашем примере сначала выполнится то, что в блоке finally, а потом уже будет return:
C#
1
2
3
4
5
6
7
8
9
10
11
12
static void Main()
{
   Foo();
   Console.ReadLine();
}
 
static void Foo()
{
   try { Console.WriteLine("Trying..."); throw new Exception(); }
   catch { Console.WriteLine("BAM!"); return; }
   finally { Console.WriteLine("Finally."); }
}
0
713 / 680 / 126
Регистрация: 30.03.2012
Сообщений: 1,124
26.12.2012, 14:34
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
 
namespace Ch10Ex01
{
    class p
    {
        static void Main()
        {
            try
            {
                throw new IOException("exc");
 
            }
            catch (IOException exc)
            {
                return;
            }
 
            finally
            {
                Console.WriteLine("В finally");
                Console.ReadKey();
            }
        }
    }
}
запустите и осознайте - finally выполняется ВСЕГДА (иначе зачем бы он был нужен?)
з.ы. а 3й вариант тут видно невооруженным взглядом - другой Exception отличный от IOException
0
быдлокодер
 Аватар для kravam
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,705
26.12.2012, 15:21  [ТС]
Цитата Сообщение от kolorotur Посмотреть сообщение
В вашем примере сначала выполнится то, что в блоке finally, а потом уже будет return:
признаться, не ожидал. Я думал, что return он return ОДНОЗНАЧНО, а тут оказывается вон оно как! А тогда вопрос возникает- почему мы вообще решаем, что выполняется вот этот return:
C#
1
2
3
4
            catch (IOException exc)
            {
                return;
            }
Основание так думать?

тут после блока finally должна быть надпись "после всего", но её нет, поскольку(???) в catch присутствует return
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
 
namespace Ch10Ex01
{
    class p
    {
        static void Main()
        {
            try
            {
                throw new IOException("exc");
 
            }
            catch (IOException exc)
            {
                Console.WriteLine("в catch");
                //return;
            }
 
            finally
            {
                Console.WriteLine("В finally");
                Console.ReadKey();
            }
            Console.WriteLine("после всего!");
        }
    }
}


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

"если в catch обнаружен оператор return, то программа выполнит его после того, как выполнит блок finally"

нет. Опыт вещь орошая. но хотелось бы об этом прочесть где-нибудь.

Добавлено через 6 минут
а вот и порядок выполнения блоков подоспел, я там жирным выделил чё надо
>> Выполнение блока try останавливается в точке, где возникло исключение.

>> Если существует какой-нибудь блок catch, выполняется проверка, соответствует ли
этот блок типу сгенерированного исключения. Если блока catch нет, выполняется
блок finally (который, если нет ни одного блока catch, должен присутствовать
обязательно).

>> Если блок catch существует, но не тот, выполняется проверка, существуют ли
другие подходящие блоки catch.

>> Если имеется совпадающий с типом исключения блок catch, выполняется
содержащийся в нем код, после чего выполняется блок finally, если он есть.


>> Если не обнаружено ни одного совпадающего с типом исключения блока catch,
выполняется блок кода finally, если он есть.

0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
26.12.2012, 15:33
Цитата Сообщение от kravam Посмотреть сообщение
Основание так думать?
Да всё логично: блок finally создан для того, чтобы можно было гарантированно "прибраться" за собой, вне зависимости от того, что происходит в методе. В блоке catch может вылететь другое исключение, которое уже не перехватится, в блоке try или catch может быть return или тот же пресловутый goto, но finally будет выполнен вне зависимости от того, что происходит в этих блоках - в этом его задача и это поведение гарантируется рантаймом (за редкими исключениями).

Цитата Сообщение от kravam Посмотреть сообщение
Если имеется совпадающий с типом исключения блок catch, выполняется
содержащийся в нем код, после чего выполняется блок finally, если он есть.
Все правильно.
Сначала выполняется код в catch, но если частью этого кода является команда, выводящая выполнение за пределы блока, то сначала делается ответвление на блок finally, после чего выполнение уже переходит туда, куда нужно.
Согласно спецификации, выполнение блока finally гарантируется в любом случае, не приводящем к полному завершению приложения - как ни пытайтесь его "обойти".

Цитата Сообщение от kravam Посмотреть сообщение
хотелось бы об этом прочесть где-нибудь.
Есть же спецификация языка - там все это прописано.
1
быдлокодер
 Аватар для kravam
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,705
26.12.2012, 17:03  [ТС]
Цитата Сообщение от kolorotur Посмотреть сообщение
Сначала выполняется код в catch, но если частью этого кода является команда, выводящая выполнение за пределы блока, то сначала делается ответвление на блок finally, после чего выполнение уже переходит туда, куда нужно.
похоже на то. Убеждает:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
 
namespace Ch10Ex01
{
    class p
    {
        static void Main()
        {
            try
            {
                throw new IOException("exc");
 
            }
            catch (IOException exc)
            {
                Console.WriteLine("в catch");
                goto metka;
            }
 
            finally
            {
                Console.WriteLine("В finally");
            }
        metka:
 
            Console.WriteLine("после всего!");
        }
    }
}
0
0 / 0 / 0
Регистрация: 27.03.2017
Сообщений: 3
27.03.2017, 14:17
Рискну поднять старую тему.

Подскажите, как решить конкретную задачу.
В функцию передается строка -- путь к папке. В хочу создать новую переменную с типом DirectoryInfo и дальше с ней поработать.
Проблема в том, что при создании может выпасть исключение т.к. в строке может быть не путь к папке, а любая ерунда (т.к. данные вводит пользователь).
Если исключение выпадает -- выходим из метода. Как отрабтать такую ситуацию? Код ниже выдает ошибку в последней строке.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
        private string Dir(string my_directory)
        {            
            try
            {
            DirectoryInfo di = new DirectoryInfo(my_directory);
            }
            catch (Exception ex)
            {
               return ex.Message;
            }
        // вот тут ошибка, di не определена.
        // пример с return сразу после try условный, дальше с di много работы.
        return di.ToString();
}
0
 Аватар для Harttman
69 / 69 / 28
Регистрация: 12.09.2013
Сообщений: 237
27.03.2017, 14:31
PavelAl,
C#
1
return di.ToString();
поместите в блок TryКак результат, Метод Dir Вернет, либо строку с ошибкой, либо DirectoryInfo
0
0 / 0 / 0
Регистрация: 27.03.2017
Сообщений: 3
27.03.2017, 14:58
Я специально написал что пример с return очень условный. На самом деле там идет плотная работа с папкой, файлы копируются, удаляются, есть еще попытки...

Я понял, что можно вытащить DirectoryInfo в отдельный метод, только ради того, что бы ее безопасно определить, но мне видится, что это какой то костыль.
Выше обсуждалось, что компилятор как то понимает, что ошибки не может возникнуть (как в моем примере) -- либо, если в try ошибка, мы выходим из метода с ошибкой и не доходим до второго return, а если дошли, то значит ошибки не было и переменные определены. Хотя это и не соответствует документации.

Так вот, вопрос, если я после объявления хочу работать с "di" долго и упорно, единственный вариант "безопасно" ее определить -- вытаскивать определение в отдельный метод?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
27.03.2017, 14:58
Помогаю со студенческими работами здесь

Проблема с возвращающим значением метода в блоке try-catch
Поставил блок try -catch, начало ругаться на значение return myArray;, которое должен вернуть метод. Что ни так? public static double...

Переменная объявленная на другой форме
Доброго времени суток, Господа. Начинаю работать с C# Программа должна открывать ком-порт на второй форме, а закрывать порт на...

Почему компилируется не объявленная переменная в шаблоне?
Нашел на просторах интернета такой код template<typename T> T foo(int x, T ololo) { a = 5; } int main() {

Почему переменная объявленная static работает не корректно?
Переменная j=25 я её обозначил как static int j; и присвоил число 25. Значит эта переменная должна сохраняться и при выходе из функции....

Ошибка в с try - catch блоке
//--------------------------------------------------------------------------- #include <vcl.h> #include <Math.h> #include...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Жизнь в неопределённости
kumehtar 23.03.2026
Жизнь — это постоянное существование в неопределённости. Например, даже если у тебя есть список дел, невозможно дойти до точки, где всё окончательно завершено и больше ничего не осталось. В принципе,. . .
Модель здравоСохранения: работники работают быстрее после её введения.
anaschu 23.03.2026
geJalZw1fLo Корпорация до введения программа здравоохранения имела много невыполненных работниками заданий, после введения программы количество заданий выросло. Но на выплатах по больничным это. . .
1С: Контроль уникальности заводского номера
Maks 23.03.2026
Алгоритм контроля уникальности заводского (или серийного) номера на примере документа выдачи шин для спецтехники с табличной частью. Данные берутся из регистра сведений, по которому настроено. . .
Хочу заставить корпорации вкладываться в здоровье сотрудников: делаю мат модель здравосохранения
anaschu 22.03.2026
e7EYtONaj8Y Z4Tv2zpXVVo https:/ / github. com/ shumilovas/ med2. git
1С: Программный отбор элементов справочника по группе
Maks 22.03.2026
Установка программного отбора элементов справочника "Номенклатура" из модуля формы документа. В качестве фильтра для отбора справочника служит группа номенклатуры. Отбор по наименованию группы. . .
Как я обхитрил таблицу Word
Alexander-7 21.03.2026
Когда мигает курсор у внешнего края таблицы, и нам надо перейти на новую строку, а при нажатии Enter создается новый ряд таблицы с ячейками, то мы вместо нервных нажатий Энтеров мы пишем любые буквы. . .
Krabik - рыболовный бот для WoW 3.3.5a
AmbA 21.03.2026
без регистрации и смс. Это не торговля, приложение не содержит рекламы. Выполняет свою непосредственную задачу - автоматизацию рыбалки в WoW - и ничего более. Однако если админы будут против -. . .
1С: Программный отбор элементов справочника по значению перечисления
Maks 21.03.2026
Установка программного отбора элементов справочника "Сотрудники" из модуля формы документа. В качестве фильтра для отбора служит значение перечислений. / / Событие "НачалоВыбора" реквизита на форме. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru