2010-02-03 29 views
3

我的问题是这样的:为什么try块中的代码与方法的其余部分分离?

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块中的代码不会与其余代码保持分开(我忘记了这个词,可能是封装?) - 类似于一个方法。

我该怎么做呢?假如WebRequest没有抛出异常,我应该在try块中复制代码吗?

+1

我想你要找的字范围。 – 2010-02-03 15:17:56

+0

其实,这是明确的任务。 – SLaks 2010-02-03 15:18:36

回答

12

您误解了错误。

request变量在所有代码的范围内。但是,在try块之外,不保证有值,并且C#编译器不会允许您使用变量,除非可以确定该变量已被分配。

具体而言,如果WebRequest.Create引发异常,则不会将request分配给。

您可以通过catch块外赋值,这样解决它:

HttpWebRequest request = null; 

顺便说一句,你不应该使用catch块的都在这里。
而应该拨打Uri.TryCreate

+2

我现在明白了 - 谢谢! – Ross 2010-02-03 14:59:30

+2

实际上并不是'request'变量不能保证在'catch'块中有一个值,而是在整个受保护区域(try/catch对)执行完之后它不能保证有一个值。 – 2010-02-03 15:18:25

+0

@斯科特:你是对的;我误解了这个问题。固定。 – SLaks 2010-02-03 15:19:53

6

为了解决这个问题,你会给请求一个默认值,如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(); 

会失败,因为在新的范围,只有通过arequest去执行路径。与try-catch一样。 trycatch都应该设置请求变量。


块范围也是相当有用的,这样是有效的:

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

// second-part 
{ 
    string myVariable = "hi"; // is valid 
} 
+2

这是不正确的。这里的问题是明确的分配,而不是范围。 – SLaks 2010-02-03 15:04:49

+2

我必须同意SLaks;问题中给出的代码示例不同意这个答案。 – Powerlord 2010-02-03 15:07:59

2

如果有抛出,则您的请求对象将是空的,因此最后一行将失败,空引用异常。

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

为真,响应也应该在try块中设置,+1 – Pharabus 2010-02-03 15:00:20

+0

实际上,它不应该。 'request.GetResponse'不能抛出'UriFormatException'。 – SLaks 2010-02-03 15:02:31

+1

@Slaks。 WebRequest.Create将抛出异常。当它应用程序将继续运行在catch块之后。如@Rob Fonseca-Ensor的例子,该方法应该结束,或者在创建请求之后在try块中检索响应。这样我们知道我们的请求被正确创建。可以为GetResponse引发的异常添加其他catch块,如下所列:http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.getresponse.aspx – 2010-02-03 15:12:55

-2

是由于范围不幸的是,你可以ammend第一线

HttpWebRequest request = null; 

,并且将修复它,基本上代码的作用范围withing try块所以外面什么也不会意识到值已设置

+3

这完全是错误的。范围在这里不是问题;问题在于第一行可能会引发异常,所以可能根本没有设置值。 – SLaks 2010-02-03 15:02:50

+0

恐怕我不同意,在他的例子中,没有在与他尝试使用它的范围相同的范围内为该请求设置值,这就是为什么设置为空作品 – Pharabus 2010-02-03 15:32:05

+0

你错了。范围与明确的分配无关。这里的问题是try块在分配发生之前可能已经终止。 – SLaks 2010-02-03 15:56:20

0

只需设置

HttpWebRequest request = null; 

的代码在try集团k在内部范围内。

当您尝试获得您的回复时,您需要检查HttpWebRequest是否为空。

2

你喜欢的样子:

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(); 

否则你只是得到一个空指针异常会掩盖原有错误

0

您可以明确设置请求在您的声明为null,那么你可以在你使用它时检查它是否为空。

0

要理解这一点,首先需要了解的范围和声明空间一点点:

范围定义了,同时声明空间集中在 如该名称是唯一可以使用的名称 。范围和 申报空间密切相关, 但有几个微妙的 差异。

更正式的定义 是范围是封闭的上下文 或区域,其限定其中名称 可以不加限定地使用。

在 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(); 
} 
相关问题