.net - 使用在 "with" block 内分配的实例的成员会抛出 System.NullReferenceException

标签 .net vb.net visual-studio

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

关于.net - 使用在 "with" block 内分配的实例的成员会抛出 System.NullReferenceException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19325070/

相关文章:

c# - .csproj 文件中未通知时,Visual Studio 如何确定输出路径?

ios - Facebook 在 Visual Studio 的 Xamarin ios 中以编程方式注销

.net - 如何使用 VB.NET 从 FTP 下载目录

.net - 将空字符串分配给当前值为空的属性

vb.net - 设置范围值时不评估 Excel 命令

c# - 更新 IQueryable 对象中的值

vb.net - Reporting Services 2008 表达式中的 vbtab

vb.net - 检查 datagridview 中的特定数据类型

c# - .NET 是否有任何框架来填充测试数据?

c# - 在目录中查询完整的文件(不是正在进行的复制)