VB.net 类对象引用未设置为对象的实例

VB.net Class Object reference not set to an instance of an object

提问人:user9671207 提问时间:10/25/2018 最后编辑:Joel Coehoornuser9671207 更新时间:10/26/2018 访问量:1792

问:

我知道这个问题以前被问过很多次,但在阅读了所有回复后,我就是无法解决。我不知道我做错了什么,现在已经看了 2 天了。 我有一个嵌套类,只是试图为它赋值,但我不断收到此错误。调试并没有让我走得更远。

我的类定义:

Public Class DocumentHeader
    Private _username As String
    <JsonProperty("username")> _
    Public Property username() As String
        Get
            Return _username
        End Get
        Set(ByVal value As String)
            _username = value
        End Set
    End Property

    Private _bus_act As String
    <JsonProperty("bus-act")> _
    Public Property bus_act() As String
        Get
            Return _bus_act
        End Get
        Set(ByVal value As String)
            _bus_act = value
        End Set
    End Property

    Private _ref_doc_no As String
    <JsonProperty("ref-doc-no")> _
    Public Property ref_doc_no() As String
        Get
            Return _ref_doc_no
        End Get
        Set(ByVal value As String)
            _ref_doc_no = value
        End Set
    End Property

    Private _header_txt As String
    <JsonProperty("header-txt")> _
    Public Property header_txt() As String
        Get
            Return _header_txt
        End Get
        Set(ByVal value As String)
            _header_txt = value
        End Set
    End Property

    Private _comp_code As String
    <JsonProperty("comp-code")> _
    Public Property comp_code() As String
        Get
            Return _comp_code
        End Get
        Set(ByVal value As String)
            _comp_code = value
        End Set
    End Property

    Private _pstng_date As String
    <JsonProperty("pstng-date")> _
    Public Property pstng_date() As String
        Get
            Return _pstng_date
        End Get
        Set(ByVal value As String)
            _pstng_date = value
        End Set
    End Property

    Private _trans_date As String
    <JsonProperty("trans-date")> _
    Public Property trans_date() As String
        Get
            Return _trans_date
        End Get
        Set(ByVal value As String)
            _trans_date = value
        End Set
    End Property

    Private _fis_period As String
    <JsonProperty("fis-period")> _
    Public Property fis_period() As String
        Get
            Return _fis_period
        End Get
        Set(ByVal value As String)
            _fis_period = value
        End Set
    End Property

    Private _doc_date As String
    <JsonProperty("doc-date")> _
    Public Property doc_date() As String
        Get
            Return _doc_date
        End Get
        Set(ByVal value As String)
            _doc_date = value
        End Set
    End Property

    Private _doc_type As String
    <JsonProperty("doc-type")> _
    Public Property doc_type() As String
        Get
            Return _doc_type
        End Get
        Set(ByVal value As String)
            _doc_type = value
        End Set
    End Property
End Class

这是我的主要课程:

Public Class RootObjectInvoice

    Private _document_header As DocumentHeader
    Public Property document_header() As DocumentHeader
        Get
            Return _document_header
        End Get
        Set(ByVal value As DocumentHeader)
            _document_header = value
        End Set
    End Property
End Class

到目前为止,我认为一切都很好。
现在是我的代码:

Dim Root As RootObjectInvoice
Dim Document_Header As DocumentHeader
Root = New RootObjectInvoice
Document_Header = New DocumentHeader
Try
    Document_Header = Root.document_header
    Document_Header.bus_act = "AAAA"

在这条线上,我得到了.我在这里缺少一些关于如何初始化对象的内容。
任何意见将不胜感激。
Document_Header.bus_act = "AAAA"NullpointerException

由于现在有效,我在以下方面遇到了问题(我习惯了 C#,而不是 VB) 我将此属性添加到 RootObjectInvoice 中

Private _metadata As List(Of Metadata)
Public Property metadata() As List(Of Metadata)
    Get
        Return _metadata
    End Get
    Set(ByVal value As List(Of Metadata))
        _metadata = value
    End Set
End Property

然后尝试初始化它:

Dim Meta_Data() As List(Of Metadata)
Root.metadata() = New List(Of Metadata)
Meta_Data = Root.metadata

但是最后一行给了我以下错误:

“System.Collections.Generic.List(Of Metadata)”类型的值不能转换为“System.Collections.Generic.List(Of Metadata)的一维数组”。

vb.net json.net NullReferenceException

评论

0赞 jmcilhinney 10/25/2018
你做什么取决于你,但我强烈建议使用标识符的标准命名约定,例如 对于局部变量而不是属性,而不是 。documentHeaderDocument_HeaderDocumentHeaderdocument_header
0赞 jmcilhinney 10/25/2018
请不要在已回答的现有帖子中添加新问题。如果您有新问题,请发布新问题。
0赞 jmcilhinney 10/25/2018
问题在于您将变量声明为数组。变量名称上的括号表示它是指定类型的数组,而不仅仅是指定类型的数组。你想要的而不是Meta_DataDim Meta_Data As List(Of Metadata)Dim Meta_Data() As List(Of Metadata)

答:

4赞 jmcilhinney 10/25/2018 #1

当然,这句话:

Document_Header = Root.document_header

应该是相反的,即

Root.document_header = Document_Header

顺便说一句,提供这样的属性的完整实现是没有意义的:

Private _document_header As DocumentHeader

Public Property document_header() As DocumentHeader
    Get
        Return _document_header
    End Get
    Set(ByVal value As DocumentHeader)
        _document_header = value
    End Set
End Property

当你可以这样做时:

Public Property document_header() As DocumentHeader

并实现同样的事情。仅当需要执行除 get 和设置支持字段以外的其他操作(例如验证新值或引发事件)时,才应提供完整的实现。

评论

1赞 user9671207 10/25/2018
谢谢,事实上,当我用 Root.document_header = New DocumentHeader 替换它时,它可以工作。现在有道理了。关于格式,我相信我必须这样做,因为它是一个旧项目,我需要使用 VS2008。这是对的吗?
1赞 jmcilhinney 10/25/2018
我不记得自动属性是什么时候添加到 VB 的,但您可能是对的,它们在 VB 2008 中不受支持。但是,您真的必须使用 VB 2008 吗?您可以在较新版本的 VS 中打开旧项目,它通常可以正常工作。但是,对于旧的东西,有一个升级过程,这将对解决方案和项目文件进行更改,使其无法再在 VS 2008 中打开。如果您需要这种兼容性,请不要升级它。
0赞 user9671207 10/25/2018
事实上,我尝试了内联属性设置,但它在 VS2008 中不起作用。我用与同一对象相关的另一个问题更新了我的初始问题。它们都被定义为 List OF,那么为什么它会抛出这个错误呢?谢谢
1赞 Joel Coehoorn 10/25/2018 #2

类型是 ,类是引用类型。所以看看这行代码:DocumentHeaderClass

Private _document_header As DocumentHeader

这里,是引用类型的变量;它希望在内存中保存对对象的引用。这是错误消息的“对象引用”部分。但此时,变量的值仍为 or 。该代码还用属性包装了该变量,但这并没有真正改变任何内容。_document_headernullNothingdocument_header

后来,我们有了这样的代码:

Dim Root As RootObjectInvoice
Dim Document_Header As DocumentHeader
Root = New RootObjectInvoice
Document_Header = New DocumentHeader

我们看到一个 类型的变量。我们还创建该类型的实例并将其分配给变量,并创建前面讨论的标头类型的实例并将其分配给单独的变量。RootRootObjectInvoiceDocument_Header

现在,我们的变量引用一个实例,并且该类型具有 type 的属性。RootRootObjectInvoiceRootObjectInvoicedocument_headerDocumentHeader

但是document_header属性仍然没有价值! 创建引用类型的实例不会自动为该类型的引用属性或成员创建实例。 仍为 null/Nothing。Root.document_header

接下来我们有了这段代码:

Document_Header = Root.document_header
Document_Header.bus_act = "AAAA"

因此,我们有一个名为 reference 变量的变量,它没有设置为对象的实例。我们将这个空引用分配给变量......这会丢弃刚刚创建的实例。哎呀;真是浪费。然后,我们尝试访问该空引用上的属性。Root.document_headerDocument_Header

这就是让事情爆炸并抛出异常的原因。

您有一个名为的对象引用变量,该变量不再分配任何值。您之前创建和分配的对象实例已被丢弃,并且不再设置。然后,您尝试取消引用此变量,以便可以访问属性,但那里什么都没有Document_Header

所以你有这个问题:

我在这里缺少一些关于如何初始化对象的内容。

您可以这样做:

Dim Root As New RootObjectInvoice()
Root.document_header = New DocumentHeader()

或者,您可以在以下类型中添加构造函数或初始值设定项:RootObjectInvoice

Private _document_header As New DocumentHeader

由于这一行,我需要进一步解决后续编辑问题:

Dim Meta_Data() As List(Of Metadata)

旁边的额外括号使它成为数组变量。你在那里声明的是一个列表数组。你只想要这个:Meta_Data()

Dim Meta_Data As List(Of MetaData)

仅对数组或 Property 声明使用括号。此外,您希望此变量实际引用 New 对象。你可以把它放在与声明相同的行上:

Dim Meta_Data As New List(Of Metadata)()

就像您在 C# 中编写以下内容一样:

var Meta_Data = new List<Metadata>();

但是,由于您确实希望它成为变量的一部分,因此您可以完全跳过该中间变量:RootMeta_Data

Root.metadata = New List(Of Metadata)()

就像在 C# 中一样,你可以这样写:

Root.metadata = new List<Metadata>();

但这实际上是糟糕的做法。在大多数情况下,当类将集合类型作为成员属性时,该属性应仅提供 Get 访问权限这在 C# 中也是如此。

您希望在类中声明属性,如下所示:

Private _metadata As New List(Of Metadata)
Public Property metadata() As List(Of Metadata)
    Get
        Return _metadata
    End Get
End Property

您仍然可以使用该属性来执行您期望的所有操作,包括添加新项,即使没有 .你唯一不能做的就是从类下完全改变集合;不能为属性分配其他 List 实例。同样,在 C# 中,定义 List 属性通常是更好的做法,如下所示:Set

private List<Metadata> _metadata = new List<Metadata>();
public List<Metadata> metadata 
{
   get {return _metadata;}
}

从 C# 6 开始,您甚至可以这样做:

public List<Metadata> metadata {get;} = new List<Metadata>();