Ссылка на объект класса VB.net не установлена ​​на экземпляр объекта - PullRequest
0 голосов
/ 25 октября 2018

Я знаю, что этот вопрос задавался много раз прежде, но я просто не могу решить его после прочтения всех ответов.Я понятия не имею, что я делаю неправильно и смотрю на это уже 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)».

Ответы [ 2 ]

0 голосов
/ 25 октября 2018

Тип DocumentHeader - это Class, а классы - ссылочные типы .Посмотрите на эту строку кода:

Private _document_header As DocumentHeader

Здесь _document_header - переменная для ссылочного типа;он хочет хранить ссылку на объект в памяти.Это часть «Ссылка на объект» сообщения об ошибке.Но в настоящее время значение переменной все еще равно null или Nothing.Код дополнительно оборачивает эту переменную свойством 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 типа DocumentHeader.

Но свойство document_header по-прежнему не имеет значения! Создание New экземпляра ссылочного типа не приводит к автоматическому созданию экземпляра для ссылочных свойств или членов типа. Root.document_header по-прежнему равно нулю / ничего.

Далее мы имеемэтот код:

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

Итак, у нас есть ссылочная переменная с именем Root.document_header, которая не установлена ​​для экземпляра объекта.Мы присваиваем эту пустую ссылку переменной Document_Header, которая отбрасывает только что созданный экземпляр.К сожалению,какая трата.Затем мы пытаемся получить доступ к свойству по этой пустой ссылке.

Вот что заставляет вещи взорваться и вызвать исключение.

У вас есть переменная ссылки на объект с именем Document_Header, которой больше не присваивается значение .Экземпляр объекта, который вы ранее создали и назначил, был отброшен и больше не задан.Затем вы пытаетесь отменить ссылку на эту переменную, чтобы получить доступ к свойству, но там ничего нет .

Итак, у вас есть вопрос:

I 'м здесь что-то не хватает, как инициализировать объект.

Вы можете сделать это:

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() делают эту переменную array .То, что вы объявили, это массив списков .Вы просто хотите это:

Dim Meta_Data As List(Of MetaData)

Используйте только скобки для массива или Property объявлений.Кроме того, вы хотите, чтобы эта переменная фактически ссылалась на новый объект.Вы можете поместить это вместе в той же строке, что и объявление:

Dim Meta_Data As New List(Of Metadata)()

Так же, как вы могли бы написать следующее в C #:

var Meta_Data = new List<Metadata>();

Но так как вы действительно хотите, чтобы это было частьюпеременной Root, вы можете полностью пропустить эту промежуточную переменную Meta_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

Вы все еще можете использовать свойство, чтобы делать всевы ожидаете, включая добавление новых предметов, хотя Set нет.Единственное, что вы не можете сделать, это полностью изменить коллекцию из-под класса;Вы не можете назначить другому экземпляру List свойство.Точно так же в C # обычно лучше определять свойство List следующим образом:

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

А в C # 6 вы даже можете просто сделать это:

public List<Metadata> metadata {get;} = new List<Metadata>();
0 голосов
/ 25 октября 2018

Конечно, эта строка:

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

и достичь того же самого.Вы должны предоставлять полную реализацию только в том случае, если вам нужно сделать что-то другое, кроме как получить и установить вспомогательное поле, например, подтвердить новое значение или вызвать событие.

...