2010-04-30 35 views
7
//always works, returning a valid object into _page 
     _page = _httpContext.Handler as System.Web.UI.Page; 

//Fails throwing the exception : Unable to cast object of type 'System.Web.DefaultHttpHandler' to type 'System.Web.UI.Page' 
     _page = (System.Web.UI.Page)_httpContext.Handler; 

我想知道爲什麼會發生這種情況?爲什麼'as'關鍵字在()投影不起作用的情況下工作

編輯:

   //Fixes the problem 
      if(_httpContext.Handler is System.Web.UI.Page) 
      _page = (System.Web.UI.Page)_httpContext.Handler; 

如果我調試「爲」關鍵字聲明,我從來沒有得到一個空引用(對象總是正確分配)。但是,()強制除非具有if語句,否則會創建異常。

編輯:經過約15通過班級運行後,我能夠得到一個空。似乎需要更多的運行才能找到空值,而(()強制轉換能夠捕獲異常的速度有多快。

OLD:每當類運行時都會在'as'語句中進行調試時,斷點命中 - 永不爲空。

當if中的'()'語句中有調試時,每次中斷點擊中演員正常工作。 Werid

回答

14

//總是工作,返回一個有效的對象到_page _page = _httpContext.Handler作爲System.Web.UI.Page;

這並沒有技術上的工作。如果你會發現_pagenull。它只是沒有拋出一個錯誤。

as運算符用於告訴應用程序「我希望您嘗試轉換它,它可能不會,我知道這一點,所以不要拋出異常,我會相應地處理它。

()轉換用於告訴應用程序:「該對象將轉換爲此類型,如果它沒有錯誤,並且我需要知道它。」

兩個類型轉換(當你要使用它們)之間的區別是,當你「想」什麼是強制轉換爲另一種類型,當你「知道」什麼是強制轉換爲另一種類型。 http://blogs.msdn.com/ericlippert/archive/2009/10/08/what-s-the-difference-between-as-and-cast-operators.aspx

0

如果使用'as'運算符,如果轉換失敗,它只會返回null。如果你做了明確的轉換,如果轉換失敗,它將會拋出一個異常。在這種情況下,'as'向下轉換爲預期的正確類型。顯式轉換不能移動到所需的類型。作爲一般規則,除非確實需要顯式強制轉換(例如當需要轉換爲值類型時),否則應始終執行「as」。

+0

我不相信。我寧願做Class1 foo =(Class1)欄,並獲得轉換異常,而不是稍後使用foo.Property或foo.Method()獲取不是有用的null異常。 null異常可能發生在「as」範圍之外的任何地方。如果我期望代碼有時會失敗,那麼我將使用「as」並檢查null。 – 2010-04-30 19:54:28

+0

這是一般模式。你用'as'進行轉換,然後檢查是否爲空。 – Tejs 2010-04-30 20:10:20

7

From here:

使用的運營商從 投在C#中的三個重要方面有所不同:

它返回null當你 正試圖轉換的變量是 請求的類型不或者在它繼承 鏈,而不是拋出 異常。它只能應用於 引用類型變量,轉換爲 引用類型。使用不會 執行用戶定義的轉換,例如 作爲隱式或顯式轉換 運算符,其中的鑄造語法將 做。其實有在IL 定義的處理這兩個關鍵字(在 castclass和isinst指令)兩個完全不同的 操作 - 它不只是「語法糖」 用C#編寫獲得此不同 行爲。 as運算符似乎 在v1.0和相比,鑄造 微軟的CLR的1.1版速度稍快(甚至在情況下,有沒有 無效蒙上這將嚴重 下鑄造的性能,因爲 例外)。

+0

但爲什麼演員不工作?我知道Handler是一個System.Web.UI.Page。我也google了一下並閱讀你發佈的內容。仍然感覺不到。 – Mausimo 2010-04-30 19:51:23

+0

「它只能應用於引用類型變量轉換爲引用類型」實際上不是真的 - 值可以是任何類型,並且目標類型也可以是可爲null的值類型。所以例如'(int)0 as IEquatable '是有效的,特別是'(object)o as int?'是一個很好的方法來檢查'o'是否是一個盒裝的'int'而不捕獲異常。它還可以讓你將諸如'(T?)x'之類的東西寫成U?',這在泛型代碼中可能稍微有用。 – 2010-04-30 19:52:03

+3

@Maus它實際上不工作。第一行實際上會將'null'放入_page,看起來不像你期望的那樣 – Earlz 2010-04-30 19:52:57

0

使用as嘗試該對象強制轉換爲特定類型,但返回null失敗,而不是拋出一個異常(而鑄剛拋出異常)。你確定as子句中的那個實際上是返回一個非空對象嗎?

+0

我把編輯,我能找到一個空。 – Mausimo 2010-04-30 20:15:38

0

同樣的事情,@Tejs回答說:

下面是埃裏克利珀關於這個問題的文章(改變他的博客不會重新feeded)。 as轉換失敗,則會生成null。

我會說從他身上不同,但並作爲一般規則,你應該總是使用顯式類型轉換。我個人倒還是願意得到一個異常身在何方轉換失敗,而不是在另一個頁面獲得(貌似)憑空空引用異常。

一個很好用的as運營商雖然是轉換的事情,當從數據庫中,而不是想檢查System.DBNull

int someint = cmd.ExecuteScalar() as int? ?? 0; 
4

一個主要之間作爲演員和前綴投不同的是,前綴投會拋出一個異常而as cast將只返回null。

0

其實,這正是是應該發生的。演員陣容失敗,投擲失敗,因爲演員陣容無效。如果轉換失敗,as默認爲空。

0

正如其他答案已經注意到的,它歸結爲「as」將在無效投射時返回null,而明確投射將拋出異常

其他答案有一些辯論是否傾向於一個或另一個。如果你要使用「是」,你需要處理在某點的事實,它可能是一個空。如果你打算使用明確的演員,你必須處理一個可能的例外。根據使用情況,我傾向於一個或另一個。

我傾向於使用特定的演員陣容,當我知道演員陣容將會工作但編譯器不會,並且拋出一個例外情況會好起來(因爲這是一個例外情況)。但是,如果演員陣容無效的合理機會,我寧願使用「as」並測試null。這樣可以避免捕捉到醜陋的異常,並使IMO調試更加困難。

相關問題