我们有一个属性,其工作是查找描述。如果查找失败,它应该显示一个空字符串。
所以我们可以像这样对属性进行编码:
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
关键字(我不做)或{{1}}关键字构建异常是昂贵的是否意味着允许异常发生是很昂贵的(正如我将要做的那样)。
答案 0 :(得分:8)
如果肯定会测试Nothing
而不是依赖于例外。您的代码表示foo.bar
为Nothing
的方案是预期方案,而不是例外方案。这样就给出了答案。
抛出异常是一项相对昂贵的操作(从性能角度来看)。无论你是在代码中抛出它,还是在库代码中抛出它,都是这种情况;这是完全相同的操作。但是,除非我有一个真实的,有计划的,关键的商业案例,否则我不会因性能原因而抛出异常。
在我看来,这主要是表达意图的问题;通过测试Nothing
并优雅地对其进行操作,您的代码表达了这不会发生奇怪的事实。
如果您担心执行foo.bar
两次的性能,首先要做的是找出是否真的如此。如果是这样,可能有解决方法(您的代码示例已包含建议)。
答案 1 :(得分:3)
我会采用这种方法:
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。它让您了解捕获异常如何影响调试性能和Release版本的性能。从语义上讲,如果出现异常情况,最好避免抛出异常,如其他答案中已经提到的那样。
答案 2 :(得分:2)
当您期望将其作为受控条件时,您应该始终尝试不进行任何测试,只使用可能的捕获来处理不需要的错误(我会广泛使用不需要的错误,因为某些错误会产生想要的结果)。在没有捕获异常的情况下处理空字符串的能力就是这样使用它。
在名为IsNullOrEmpty
或IsNullOrWhiteSpace
的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测试此变量,或者如果您想要包含空格检查,则{ {1}}(这也测试空字符串)。
这是运行的代码: