2011-05-27 81 views
9

問題1>我應該在下面的情況下檢查NULL嗎?當我們將IClass轉換爲Class時,我們應該檢查NULL嗎?

public interface INewClass {} 
public class NewClass : INewClass {} 

public void FunMeA(INewClass obj) 
{ 
    NewClass n = (NewClass) obj; 
    ... // Should I check (n == null) here? 
    // call methods defined inside INewClass (updated from NewClass to INewClass) 
    ... 
} 

A concrete example, 

public void FunMeB(IAsyncResult itfAR) 
{ 
    AsyncResult ar = (AsyncResult) itfAR; 
    ... // Should I check (ar == null) here? 
    // access ar.AsyncDelegate 
    ... 
} 

問題2>我剛剛開始從C++轉移到C#。當使用C++進行編碼時,我知道何時應該完成檢查。然而,我完全迷失在C#世界中。所以問題是:有沒有 一個可以告訴我什麼時候我必須檢查NULL的一般規則?

謝謝

+0

如果這些方法在INewClass接口上定義的,你爲什麼鑄造呢? – Massif 2011-05-27 15:23:27

+0

只需在使用函數之前檢查對象是否爲NULL。理想的情況是,當你使用該方法時,對象不能爲空,因爲它是你程序運行所必需的。 – 2011-05-27 15:28:25

回答

12

做這件事時:

NewClass n = (NewClass) obj; 

是沒有意義的,因爲如果它不投它會拋出一個無效的轉換異常。

如果您有任何懷疑你是否能真正施展它,你想做的事:

NewClass n = obj as NewClass; 

然後

if(n != null) ... 

你正在做被稱爲直接鑄造的塑像,系統會假定它可以被製造。 n = obj as NewClass被稱爲間接轉換,並且適用於那些你想要告訴程序的場景:「嘿,我認爲這樣會起作用,但如果不是,不要翻出來拋出異常......我會處理它,如果它不起作用。「

在鑄造中使用isas

取決於您希望哪一種情況比另一種好。技術上從性能角度來看as是首選。 .Net將使用原子試圖將其轉換爲所需的類型,如果不是,則返回null,如果使用is,則必須遍歷繼承樹兩次以查看它是否與該類型匹配,然後進行轉換。因此,在大多數情況下,如果你想看看,如果你想投和使用該類型最好是:

var obj = o as type 
if (obj != null) 

,而不是

if(o is type) 
{ 
    var obj = (type); 
} 
+0

-1:最後一段沒有太大意義。你認爲.NET如何確定一個演員是否與'as'關鍵字或'(SomeType)變量'語法合法?顯然必須看看繼承樹。該文檔(http://msdn.microsoft.com/en-us/library/cscsdfbt.aspx)表示as表達式等同於'expression是type? (type)expression:(type)null',只是表達式只計算一次。另外,試着看看IL。我編譯了表達式'return(value as TOut)!= null;'和Reflector將它拆分爲'return(value is TOut);' – phoog 2011-05-27 23:40:56

+0

...繼續:但是'as'運算符的IL有12條指令,相反到'is'運算符爲8。 – phoog 2011-05-27 23:44:54

+0

你說的沒錯,沒有太多意義。我修復了它。 – kemiller2002 2011-05-28 19:15:11

5

如果轉換失敗,您的代碼將拋出一個異常。

使用is運算符可以查看投射是否有效,並且as可以投射(如果投射失敗,則不會拋出並返回空值)。

所以:

if(obj is NewClass) 
{ 
    //Yay, can cast! 
} 

或者:

NewClass nc = obj as NewClass; 
if(nc != null) 
{ 
    //Yay! 
} 
+1

但是不要一起使用'是'和'as'。如果您想要處理演員無效的可能性,請使用帶空檢查的'as'。 – phoog 2011-05-27 14:41:41

+3

但是,空引用仍然可以投,當然... – 2011-05-27 14:41:54

+0

當然。我的觀點是'if(x是SomeType){var y = x as SomeType; ...}「是多餘的。 – phoog 2011-05-27 17:27:32

2

如果你想檢查空,那麼你應該做的

NewClass n = obj as NewClass ; 
if (n != null) 
{ 

... 

} 

但總的來說,你可以檢查null如果意味着在上下文中可以採取其他行動。在大多數情況下,您應該讓它拋出NullReferenceException而不是吞下它,以便您可以更快地識別空引用的原因。

+0

如果obj爲null,則此賦值不會拋出NullReferenceException:'NewClass n =(NewClass)obj;' – phoog 2011-05-27 17:40:18

+0

@phoog我的意思是說,只有在您完全知道爲什麼它爲null並且具有平均值處理這種情況。有些人在任何東西上檢查null,並在其他部分做任何事情。它不會導致運行時空指針異常,但是當出現錯誤時,很難弄清楚什麼是錯誤的。在大多數情況下,最好是直接施放而不是安全施放。 – 2011-05-27 17:55:54

+0

同意。當程序失敗時,這是非常令人沮喪的。 – phoog 2011-05-27 17:59:42

2

如果你這樣做NewClass n = (NewClass)obj如果它不能正確轉換,你會得到一個異常。

如果你希望有一個可能性爲空而不拋出異常,你會想要做NewClass n = obj as NewClass;,然後檢查n是否爲空。

您可以通過使用is運算符來檢查演員陣容是否在手邊工作。 if(obj is NewClass)

希望這會有所幫助。

+0

您可以施放空引用。試試吧,你會喜歡的。 – phoog 2011-05-27 17:28:44

2

如果參數是必需的,您應該始終檢查null並拋出ArgumentExceptionArugmentNullException

此參數檢查這裏最好的辦法是:

AsyncResult ar = itfAR as AsyncResult; 
if(ar == null) 
{ 
    // even better: Use a resource here 
    throw new ArgumentNullException("Parameter itfAR must not be null and must be of type AsyncResult"); 
} 
+0

很好的瞭解這兩個預定義的異常類。 -thx – q0987 2011-05-27 14:57:06

+1

@ q0987還有一個'ArgumentOutOfRangeException',但這當然沒有任何意義 – 2011-05-27 15:10:11

+1

這可能會導致一個誤導性的異常。例如,如果itfAR是一種實現IAsyncResult但不從AsyncResult繼承的類型,即使參數不爲null,也會引發ArgumentNullException。混亂。 – phoog 2011-05-27 17:42:08

1

我寧願投前檢查爲空。例如。

if (obj == null) 
{ 
    throw new ArgumentNullException("obj", "The argument must has a value specified"); 
} 
1

您正在混淆的問題。

  1. 您應該始終驗證公開曝光的方法的參數。因此,你要高度重視先做:

    公共WhateEverMethod(IElement iElement) { 如果(iElement == NULL){ 扔 新ArgumentNullException(...); } }

  2. 一旦驗證了該元素不爲空,您將檢查是否可以執行強制轉換。實質上你可以走兩條路:

    Element element = iElement as Element;

    if(element == null)// cast failed {0} {0} {0}拋出新的InvalidCastException(...); }

if (!(iElement is Element)) 
{ 
    throw new InvalidCastException(...); 
} 

Element element = (Element)iElement; 
+2

'Element element =(Element)(new Object());'無論如何拋出一個'InvalidCastException',爲什麼檢查並把它放在第一位!? – 2011-05-27 15:49:13

+0

我是第二個西蒙的觀點。如果演員無效是一個例外條件,那麼你自己就無法拋出一個無效的演員例外。然而,當我這樣做時,我通常會添加一條評論,這樣別人就不會認爲我忽略了無效投射的可能性並更改我的代碼:var theString =(string)obj;如果obj不是字符串,則拋出異常 – phoog 2011-05-27 17:47:35

+1

@Simon:真的,我的不好。我沒有清楚地思考。我想解決的一點是我會區分ArgumentNull和InvalidCast。但顯然是的,施放檢查是完全沒有必要的。 – InBetween 2011-05-27 17:51:20

相關問題