область видимости при окружении «нового» оператора try / catch в c # - PullRequest
0 голосов
/ 31 мая 2011

Это вопрос о том, что является «лучшей практикой» для объявления новых переменных, и я уже видел эту ситуацию несколько раз. У меня есть класс, конструктор которого читает файл конфигурации, например:

ConfigMgr config = new ConfigMgr(args[0]);

Конечно, если вы запускаете консольное приложение без этого аргумента, возникает исключение. Если я окружу эту строку с помощью try / catch следующим образом, я получу ошибку «Имя« config »не существует в текущем контексте». Понятный.

try
{
    ConfigMgr config = new ConfigMgr(args[0]);
}
catch
{
    Console.WriteLine("Config file not specified or incorrect in format.  Exiting.");
    Console.ReadLine();
}

// Defaults
string aucomposingfile = config.getValue("aucomposingfile");
string nzcomposingfile = config.getValue("nzcomposingfile");
...etc

Я мог бы выделить часть, которая требует аргумента в конструкторе - сделать новую часть ConfigMgr за пределами блока try / catch, а затем сделать что-то вроде config.LoadFile () в try / catch. Но я не могу себе представить, что это делают те, кто в курсе.

Есть мысли?

Спасибо!

Ответы [ 2 ]

3 голосов
/ 31 мая 2011

Если вам нужен доступ к переменной не только в блоке try, вам необходимо объявить и инициализацию переменной перед блоком.Достаточно просто объявить и инициализировать нулем.

Foo foo = null;
try 
{
    foo = DoSomethingToGetFoo();
}
catch (SpecificException ex)
{
    // do whatever, foo is accessible but may require null-checking
}
finally 
{
    // ditto 
}

// still accessible

Очевидно, что объявление переменной во внешней области необходимо, если вы хотите получить к ней доступ в другом месте.Но инициализация также необходима, так как компилятор C # потребует доказательства того, что переменная была инициализирована, прежде чем вы сможете использовать ее.Если «стандартный» инициализатор находится в области действия try, компилятор не может гарантировать, что это произошло до его последующего использования.

Для вашего собственного кода вы можете решить, есть ли все, что вам нужноdo с переменной может содержаться в пределах try.Если так, очевидно, ограничьте его область этим блоком.Но в некоторых ситуациях вам нужен более широкий охват.(См .: расширение using для IDisposable объектов.)

3 голосов
/ 31 мая 2011

Нет причины, по которой вы не можете сделать это:

ConfigMgr config = null;
try
{
    config = new ConfigMgr(args[0]);
}
catch ( /* catch a specific exception!! */ ) 
{
    //log it:
    Console.WriteLine("Config file not specified or incorrect in format.  Exiting.");

    //escape from here, because you don't want to continue:
    throw;    
}

string aucomposingfile = config.getValue("aucomposingfile");
string nzcomposingfile = config.getValue("nzcomposingfile");

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

...