2010-11-12 35 views
8

我們有一個財產,其工作是查找說明。如果查找失敗,它應該顯示一個空字符串。Catch NullReferenceException或首先測試Nothing?

因此,我們可以像這樣的代碼屬性:

If foo.bar Is Not Nothing Then 
    Return foo.bar.Description 
Else 
    Return String.Empty 
End If 

但是,這涉及到執行foo.bar兩次,如果這樣做是昂貴的,它可能是這樣的美好:

Dim b As bar = foo.bar 
If b IsNot Nothing Then 
    Return b.Description 
Else 
    Return String.Empty 
End If 

但我們真正想做的就是將任何一種錯誤當作空的描述。因此,在某些方面,這是簡單的:

Try 
    Return foo.bar.Description 
Catch e As NullReferenceException 
    Return String.Empty 
End Try 

但是否有任何問題(性能,純度,其它?)只捕捉和忽略錯誤?

有時你看這是昂貴拋出異常,但我不知道作者是否意味着它是昂貴的建造使用了Throw關鍵字(這我沒有做)異常或他是否意味着它是昂貴的,以允許例外發生(就像我會這樣做)。

回答

8

如果鐵定測試,而不是依靠例外這裏Nothing。您的代碼表示foo.barNothing的場景是預期場景,而不是例外之一。這樣的答案。

拋出異常是一個相對昂貴的操作(從性能角度來看)。無論您是將代碼放在代碼中,還是放入庫代碼中,都是如此。這是完全相同的操作。然而,除非我有一個真實的,嚴謹的商業案例,否則我不會因性能原因而拋出異常。

在我看來,這主要是一個顯示意圖的問題;通過測試Nothing並在其上表現優雅,您的代碼表示這並不是一件奇怪的事情。

如果你擔心在執行foo.bar兩倍的性能提升,做的第一件事就是找出如果真的是這樣。如果是這樣,可能有解決方法(你的代碼示例已經包含一個建議)。

+0

+1一個很好的,很好解釋的答案。並100%正確。 – 2010-11-12 13:30:44

2

你應該總是嘗試測試了什麼,當你期待它作爲受控狀態,只能用在可能的情況來處理不必要的錯誤(我使用不必要的廣泛一些錯誤產生想要的結果)漁獲量。在不捕捉異常的情況下處理空字符串的能力就是這樣使用它的。

使用名爲IsNullOrEmptyIsNullOrWhiteSpace String類類型內的一個空字符串測試功能:

Public Shared Sub Main() 

     Dim f As String 
     Dim b As String 

     Dim emptyResponseString As String = "I was empty" 

     'Foo will return a Null String' 

     f = foo() 

     'Bar will return an instantiated String' 

     b = bar() 

     If String.IsNullOrEmpty(f) Then 
      Console.Out.WriteLine("foo(): " & emptyResponseString) 
     Else 
      Console.Out.WriteLine("foo(): " & f) 
     End If 

     If String.IsNullOrEmpty(b) Then 
      Console.Out.WriteLine("bar(): " & emptyResponseString) 
     Else 
      Console.Out.WriteLine("bar(): " & b) 
     End If 

    End Sub 

    Public Shared Function foo() As String 
     Return Nothing 
    End Function 

    Public Shared Function bar() As String 
     Return "I am not empty!" 
    End Function 

這將讓你離開你的異常處理意外的異常(因爲它應該是^^)

在您選擇的角度看,第二個是最接近我會建議,把你的功能,導致成一個存儲變量,然後使用String.IsNullOrEmpt Y檢驗這個變量,如果你想包含空白支票,然後String.IsNullOrWhiteSpace(這也測試空海峽也是)。

下面是代碼運行:

http://ideone.com/CelDe

2

我會用這種方法去:

Dim b As bar = foo.bar 
If b IsNot Nothing Then 
    Return b.Description 
Else 
    Return String.Empty 
End If 

如果後來發現自己經常重複的代碼相同的部分,你可以用這個查找通用功能,例如:

Private Function GetPropertyOrStringEmptyIfNothing(barObj As bar, propSelector As Func(Of bar, String)) 
    If barObj IsNot Nothing Then 
    Return propSelector(barObj) 
    Else 
    Return String.Empty 
    End If 
End Function 

下面是一個使用示例:

GetPropertyOrStringEmptyIfNothing(foo.bar, Function(x) x.Description) 

它會工作,假設你有在當前範圍內聲明的同等級:

Class bar 
    Public Description As String 
End Class 

至於捕獲異常的成本,here is a link to my answer on a different question。它讓您瞭解如何捕獲異常影響調試性能以及發佈版本的性能。從語義上講,如果不是異常情況,最好避免拋出異常,正如其他答案中已經提到的那樣。