我注意到 .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.


评论关闭
IT序号网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!