C# 为什么try块中的代码与方法的其余部分是分开的?
我的问题是这样的:C# 为什么try块中的代码与方法的其余部分是分开的?,c#,exception-handling,C#,Exception Handling,我的问题是这样的: 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;
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();
HttpWebRequest request = null;
我将从中得到的错误是,request
没有被赋予一个值。显然,这是因为请求的值是在try块中给出的
这让我感到困惑的原因是,在我使用的其他语言中,try
块中的代码没有与代码的其余部分分开(我忘记了这个词,可能是封装?),这与方法类似
我走错方向了吗?如果
WebRequest
没有抛出异常,我是否应该在异常后复制try块中的代码?您误解了错误
request
变量在所有代码的范围内。但是,在try
块之外,不能保证它有一个值,并且C#编译器将不允许您使用变量,除非它可以确保变量已经被赋值
特别是,如果WebRequest.Create
抛出异常,request
将不会被分配到
您可以通过在catch
块之外指定一个值来修复它,如下所示:
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();
HttpWebRequest request = null;
顺便说一下,您不应该在这里使用
catch
块。相反,您应该调用。要解决这个问题,您应该给请求一个默认值,如
HttpWebRequest request=null代码>
C#和大多数C风格的语言(但不是JavaScript!)都有块作用域,这就是您要寻找的术语
因此,通过当前作用域的每个执行路径都应该设置请求
参数。所以
//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
设置请求的执行路径。与相同,请尝试catch
。try
和catch
都应该设置请求变量
块作用域也非常有用,如下所示:
// first-part-of-my-app
{
int myVariable = 10;
}
// second-part
{
string myVariable = "hi"; // is valid
}
如果抛出异常,那么您的请求对象将为null,因此最后一行将以null引用失败
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;
}
由于范围的原因,很遗憾,您可以将第一行
HttpWebRequest request = null;
这将解决它,基本上代码的作用域是try块,因此它之外的任何东西都不会意识到已经设置了值
HttpWebRequest request = null;
try块中的代码位于内部作用域中
当您尝试获取响应时,您需要先检查HttpWebRequest
是否为空。您觉得以下各项的外观如何:
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();
否则,您只会得到一个空指针异常,该异常将掩盖原始错误。您可以在声明中将request显式设置为null,然后在使用它时检查它是否为null。要理解这一点,您首先需要了解一点范围和声明空间:
范围定义了可以使用名称的位置
而宣言空间则侧重于
这个名字是唯一的。范围和
申报空间密切相关,
但也有一些微妙之处
差异
更正式的定义
范围是一个封闭的上下文
或定义名称所在位置的区域
可以在没有资格的情况下使用
在
C#,范围和声明空间
由语句块定义
用大括号围起来。这意味着
名称空间、类、方法和
所有属性都定义范围和范围
声明空间。因此,
作用域可以嵌套并相互重叠
其他的
try块(正确地称为受保护区域)的语言语义是受保护区域定义范围。这意味着在该范围内定义的任何变量在该范围内(以及任何嵌套范围内)仅通过名称可见
接下来您会遇到一个问题,.NET Framework强制执行类型安全的方法之一是不允许使用统一化变量。因此,由于您声明了HttpWebRequest请求代码>作为局部变量,未提供初始值。此外,由于实际提供值的唯一位置是在受保护区域内,因此编译器“足够聪明”,能够意识到受保护区域内的代码可能不会运行(由于发生异常)它能够验证执行路径是否会导致请求
从未被赋值,并发出错误
正确的处理方法是使用以下代码:
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();
}
是的,响应也应该在try块中设置,+1实际上,它不应该设置request.GetResponse
无法抛出UriFormatException
@Slaks。WebRequest.Create将引发异常。当它这样做时,该应用程序将继续在catch块之后运行。要么像@Rob Fonseca Ensor的例子那样结束该方法,要么在创建请求后在try块中检索响应。这样我们就知道我们的请求是正确创建的。可以为GetResponse引发的异常添加其他捕获块,如下所示:正确。但是,它不应位于相同的try
块中。相反,应该有一个return
语句。@Slaks我同意在try块中放入一些永远不会抛出预期异常的内容是不好的,但在这种情况下,它可能会产生最少的代码。这是完全错误的。范围不是这里的问题;问题是第一行可能会抛出异常,因此可能根本无法设置值。恐怕我不同意,在他的示例中,在他尝试使用请求的同一范围内,没有为请求设置任何值,这就是为什么设置为null是错误的。范围与明确的分配无关。这里的问题是try块可能在分配发生之前终止。这是不正确的。这里的问题是明确的任务,而不是范围;问题中给出的代码示例与此答案不一致。我认为您要查找的单词是scope.Act