2010-02-03 51 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(); 
} 
相關問題