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

时间:2018-10-25 14:08:27

标签: vb.net class json.net nullreferenceexception

我知道这个问题已经被问过很多次了,但是在阅读所有答复后我还是无法解决。我不知道自己在做什么,现在已经两天了。 我有一个嵌套的类,只是试图为其分配值,但是我一直收到此错误。调试并没有给我带来任何好处。

我的班级定义:

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) 我将此属性添加到R​​ootObjectInvoice

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)的一维数组'。

2 个答案:

答案 0 :(得分:4)

当然这行:

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

并实现相同的目的。仅在需要执行除获取和设置后备字段之外的其他事情时,才应提供完整的实现,例如验证新值或引发事件。

答案 1 :(得分:1)

DocumentHeader类型为Class,类为reference types。因此,请看这一行代码:

Private _document_header As DocumentHeader

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

稍后,我们有以下代码:

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

我们看到类型为Root的变量RootObjectInvoice。我们还将创建该类型的实例并将其分配给变量,并创建先前讨论的Document_Header标头类型的实例并将其分配给单独的变量。

现在,我们的Root变量引用了RootObjectInvoice实例,并且RootObjectInvoice类型具有类型document_header的{​​{1}}属性。

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

接下来我们有以下代码:

Root.document_header

因此,我们有一个名为Document_Header = Root.document_header Document_Header.bus_act = "AAAA" 的引用变量,它没有设置为对象的实例。我们将该空引用分配给Root.document_header变量...,该变量将丢弃刚刚创建的实例。糟糕!真是浪费然后,我们尝试访问该空引用上的属性。

这就是使事情崩溃并引发异常的原因。

您有一个名为Document_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) 旁边的多余括号使它成为 array 变量。您声明的是一个列表数组。您只想要这个:

Meta_Data()

仅对数组或 Property 声明使用括号。此外,您希望此变量实际引用一个New对象。您可以将其与声明放在同一行:

Dim Meta_Data As List(Of MetaData)

就像您可能在C#中编写以下代码一样:

Dim Meta_Data As New List(Of Metadata)()

但是,由于您确实希望将其作为var Meta_Data = new List<Metadata>(); 变量的一部分,因此可以完全跳过该中间Root变量:

Meta_Data

就像在C#中一样,您可以编写:

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

但这实际上是一种不好的做法。在大多数情况下,当类的集合类型作为成员属性时,该属性应仅提供Root.metadata = new List<Metadata>(); 访问权限在C#中也是如此。

您要在此类中声明属性:

Get

即使没有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

从C#6开始,您甚至可以执行以下操作:

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