我注意到 .NET 中有一个非常奇怪的行为,我花了一点时间才弄清楚发生了什么,因为对我来说,它不直观。假设我有以下类(class):
Public Class TestClass
Private Shared people As New Dictionary(Of Integer, Person)
Class Person
Public Property FirstName() As String
Public Property LastName As String
Public Sub SayMyName()
MsgBox(FirstName & " " & LastName)
End Sub
Public Sub New(FirstName As String, LastName As String)
Me.FirstName = FirstName
Me.LastName = LastName
End Sub
End Class
Shared Sub Test()
Dim checkPerson As Person = Nothing
With checkPerson
If (Not people.TryGetValue(3, checkPerson)) Then checkPerson = New Person("Bob", "Allen")
.SayMyName()
End With
End Sub
Shared Sub New()
people.Add(1, New Person("John", "Doe"))
people.Add(2, New Person("Jane", "Smith"))
End Sub
End Class
如果我调用 TestClass.Test()
,则调用 SayMyName()
会抛出 System.NullReferenceException。如果我正在调试,则没有明显的空引用。我最终意识到这是因为当“with” block 开始时引用为空,并且它仍然被 CLR 视为空,即使调试器显示它存在。
显然,为了清楚起见,我的示例进行了简化,但在我的实际代码中,在“with” block 之外声明实例方式然后在 block 内有条件地分配它是有用的(即,如果它之前没有在“带” block )。
有人对此有合理的解释吗?我知道我可以轻松解决这个问题,但我只是想看看人们对这种行为有何看法或了解。
请您参考如下方法:
With block
其工作方式是获取一个表达式并一次对其求值,然后允许您将其用于多个语句。
在你的情况下,在这里,当你写这个时:
With checkPerson
If (Not people.TryGetValue(3, checkPerson)) Then checkPerson = New Person("Bob", "Allen")
.SayMyName()
End With
表达式 是第一行的checkPerson
。这相当于做:
' Evaluate the expression
Dim temp = checkPerson
' Perform statements, substituting as required
If (Not people.TryGetValue(3, checkPerson)) Then checkPerson = New Person("Bob", "Allen")
temp.SayMyName()
这种行为是设计的,旨在防止在昂贵的情况下多次计算表达式,即:
With SomeExpensiveFunctionThatReturnsAnObject()
它在 With documentation 的表达式部分中有清楚的记录。 :
An expression that evaluates to an object. The expression may be arbitrarily complex and is evaluated only once. The expression can evaluate to any data type, including elementary types.