Почему код в блоке try отделен от остальной части метода? - PullRequest
3 голосов
/ 03 февраля 2010

Моя проблема выглядит примерно так:

HttpWebRequest request;

try {
    request = (HttpWebRequest) WebRequest.Create(url);
} catch (UriFormatException) {
    statusLabel.Text = "The address you entered was malformed, please correct it.";
    statusLabel.ForeColor = Color.Red;
}

HttpWebResponse response  = (HttpWebResponse) request.GetResponse();

Ошибка, которую я получу от этого, заключается в том, что request не было присвоено значение. Очевидно, это потому, что значение для запроса указано в блоке try.

Причина, по которой меня это смущает, заключается в том, что на других языках, которые я использовал, код в блоке try не отделен (я забыл слово для этого, возможно, инкапсуляция?) От остальной части кода - похоже к методу.

Я поступаю неправильно? Должен ли я продублировать код в блоке try после исключения, предполагая, что WebRequest не выбрасывает один?

Ответы [ 8 ]

12 голосов
/ 03 февраля 2010

Вы неправильно понимаете ошибку.

Переменная request находится в области действия всего кода.Однако за пределами блока try не гарантируется, что оно будет иметь значение, и компилятор C # не позволит вам использовать переменную, если только он не будет уверен, что переменная уже назначена.

Специально, если WebRequest.Create выдает исключение, request не будет назначено.

Вы можете исправить это, присвоив значение за пределами блока catch, например:

HttpWebRequest request = null;

Кстати, вам вообще не следует использовать блок catch.
Вместо этого вам следует позвонить Uri.TryCreate.

6 голосов
/ 03 февраля 2010

Чтобы решить эту проблему, вы бы запросили значение по умолчанию, например HttpWebRequest request = null;.

C # и большинство языков в стиле C (но не JavaScript!) Имеют блочную область видимости, это термин, который вы искали.

Поэтому каждый путь выполнения в текущей области должен устанавливать параметр request. Так

//create new scope (every '{ }' block has it's own scope, so you can also create
// a new one, by just wrapping some code inside accolades.
{
    if(a) request = something;
    else if(b) // do nothing
}

request.DoSomething();

Сбой, как в вашей новой области, только путь выполнения, который проходит через a, устанавливает request. То же самое с try-catch. И try, и catch должны установить переменную запроса.


Область видимости блока также весьма полезна, например:

// first-part-of-my-app
{
    int myVariable = 10;
}

// second-part
{
    string myVariable = "hi"; // is valid
}
2 голосов
/ 03 февраля 2010

Как вам нравится внешний вид:

HttpWebRequest request;

try {
    request = (HttpWebRequest) WebRequest.Create(url);
} catch (UriFormatException) {
    statusLabel.Text = "The address you entered was malformed, please correct it.";
    statusLabel.ForeColor = Color.Red;
    return;
}

HttpWebResponse response  = (HttpWebResponse) request.GetResponse();

В противном случае вы просто получите исключение нулевого указателя, которое замаскирует исходную ошибку

2 голосов
/ 03 февраля 2010

Если сгенерировано исключение, тогда ваш объект запроса будет нулевым, и поэтому последняя строка завершится с нулевой ссылкой.

HttpWebRequest request;

try {
    request = (HttpWebRequest) WebRequest.Create(url);
    HttpWebResponse response  = (HttpWebResponse) request.GetResponse();
    // do stuff with your response
} catch (UriFormatException) {
    statusLabel.Text = "The address you entered was malformed, please correct it.";
    statusLabel.ForeColor = Color.Red;
}
0 голосов
/ 03 февраля 2010

Чтобы понять это, сначала нужно немного разобраться с областью действия и областью объявления:

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

Более формальное определение заключается в том, что область действия - это включающий контекст или область, которая определяет, где имя может использоваться без квалификации.

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

Семантика языка для блока try (правильно называемого защищенной областью) заключается в том, что защищенная область определяет область действия.Это означает, что любые переменные, определенные внутри этой области видимости, видны только по имени в этой области (и любые вложенные области видимости).

Следующее, с чем вы столкнетесь, это то, что .NET Framework обеспечивает безопасность типов:запретить унифицированные переменные.В результате, поскольку вы объявляете HttpWebRequest request; как локальную переменную, ему не было предоставлено начальное значение.Кроме того, поскольку единственное место, которое фактически предоставляет значение, находится внутри защищенной области, компилятор «достаточно умен», чтобы понимать, что код внутри защищенной области может не работать (в результате возникновения исключения), он можетубедитесь, что путь выполнения может привести к тому, что request никогда не будет присвоено значение, и выдаст ошибку.

Правильный способ справиться с этим - использовать такой код:

HttpWebRequest request = null;

try 
{ 
    request = (HttpWebRequest) WebRequest.Create(url); 
}
catch (UriFormatException)
{ 
    statusLabel.Text = "The address you entered was malformed, please correct it."; 
    statusLabel.ForeColor = Color.Red; 
} 

if (request != null)
{  
   HttpWebResponse response = (HttpWebResponse) request.GetResponse(); 
}
0 голосов
/ 03 февраля 2010

Вы можете явно установить запрос в null в своем объявлении, а затем вы можете проверить, является ли он нулевым, когда вы его используете.

0 голосов
/ 03 февраля 2010

Просто установите

HttpWebRequest request = null;

Код в блоке try находится во внутренней области.

Когда вы пытаетесь получить ответ, вам нужно проверить, является ли HttpWebRequest нулевым.

0 голосов
/ 03 февраля 2010

это связано с областью применения, к сожалению, вы можете изменить первую строку до

HttpWebRequest request = null;

и это все исправит, в основном код ограничен блоком try, поэтому все, что находится за его пределами, не будет знать, что было установлено значение

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...