2010-11-12 38 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。它让您了解如何捕获异常影响调试性能以及发布版本的性能。从语义上讲,如果不是异常情况,最好避免抛出异常,正如其他答案中已经提到的那样。