Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/svn/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 使用在“中指定的实例的成员”;加上;块抛出System.NullReferenceException_.net_Vb.net_Visual Studio - Fatal编程技术网

.net 使用在“中指定的实例的成员”;加上;块抛出System.NullReferenceException

.net 使用在“中指定的实例的成员”;加上;块抛出System.NullReferenceException,.net,vb.net,visual-studio,.net,Vb.net,Visual Studio,我注意到.NET中有一个非常奇怪的行为,我花了一点时间才弄清楚到底发生了什么,因为对我来说,这不是直觉。假设我有以下类别: Public Class TestClass Private Shared people As New Dictionary(Of Integer, Person) Class Person Public Property FirstName() As String Public Property LastName As S

我注意到.NET中有一个非常奇怪的行为,我花了一点时间才弄清楚到底发生了什么,因为对我来说,这不是直觉。假设我有以下类别:

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”块启动时引用为null,并且CLR仍然将其视为null,即使调试器显示它存在

显然,为了清晰起见,我的示例进行了简化,但在我的实际代码中,在“with”块之外声明实例方式,然后在块内部有条件地分配它是有用的(即,如果它之前没有在“with”块之外分配)


有人对此有合理的解释吗?我知道我可以很容易地解决这个问题,但我只是好奇人们对这种行为的看法或了解。

带有的
块捕获您传递的表达式的当前值,一次。(它将此值存储在编译器生成的隐藏变量中)

如果它按照您希望的方式运行,那么使用SomeSlowFunction()编写
将对块中的每一行代码再次调用该函数。

该函数的工作原理是取一个表达式并对其求值一次,然后允许您对多个语句使用该表达式

在您的情况下,在这里,当您编写以下内容时:

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()
在以下内容的表达部分中有明确的记录:

计算结果为对象的表达式。表达式可以是任意复杂的,并且只计算一次。表达式可以计算为任何数据类型,包括基本类型


当你写这个--
checkPerson=newPerson(“鲍勃”、“艾伦”).SayMyName()
时,它不是将“checkPerson”设置为“SayMyName”的返回值吗?“我很惊讶它能编译。@McGarnagle——它不是一行,而是两行。”。“.SayMyName()”是一个单独的调用。@McGarnagle With块使该调用成为一个完全独立的代码行,与上面的语句无关。在这方面,它的行为与其他语言(如C#)不同。谢谢大家。这很有道理。