Задайте тип настраиваемой переменной по значению [duplicate]

Ссылка NullReferenceException или Object, не установленная на экземпляр объекта, возникает, когда объект класса, который вы пытаетесь использовать, не создается. Например:

Предположим, что у вас есть класс с именем Student.

public class Student
{
    private string FirstName;
    private string LastName;
    public string GetFullName()
    {
        return FirstName + LastName;
    }
}

Теперь рассмотрим другой класс, в котором вы пытаетесь получить полное имя учащегося.

public class StudentInfo
{      
    public string GetStudentName()
    {
        Student s;
        string fullname = s.GetFullName();
        return fullname;
    }        
}

Как видно из вышеприведенного кода, оператор Student s - объявляет только переменную типа Student, обратите внимание, что класс Student не создается в этой точке. Следовательно, когда выполняется выполнение инструкции s.GetFullName (), она выкинет исключение NullReferenceException.

24
задан Brian Hooper 26 January 2011 в 17:18
поделиться

3 ответа

Как и многие современные языки, VB6 имеет типы значений и ссылочные типы. Классы определяют ссылочные типы. С другой стороны, ваши основные типы, такие как Integer, являются типами значений.

Основное различие заключается в назначении:

Dim a as Integer
Dim b as Integer
a = 2
b = a
a = 1

В результате a равно 1 и b равно 2. Это потому, что присваивание в типах значений делает копию. Это потому, что каждая переменная имеет пространство, выделенное для значения в стеке (в случае VB6, Integer занимает 2 байта в стеке).

Для классов это работает иначе:

Dim a as MyClass
Dim b as MyClass
Set a = New MyClass
a.Value1 = 2
Set b = a
a.Value1 = 1

В результате обе a.Value1 и b.Value1 равны 1. Это потому, что состояние объекта хранится в куче, а не в стеке. В стек хранится только ссылка , поэтому Set b = a перезаписывает ссылку. Интересно, что VB6 явно говорит об этом, заставляя использовать ключевое слово Set. Большинство других современных языков этого не требуют.

Теперь вы можете создавать свои собственные типы значений (в VB6 они называются User Defined Types, но на большинстве других языков они называются структурами или структурами) , Вот учебник .

Различия между классом и определенным пользователем типом (кроме класса, являющегося ссылочным типом и UDT, являющегося типом значения) состоит в том, что класс может содержат методы (методы и свойства), в которых UDT не может. Если вы просто ищете класс типа записи, тогда может быть вашим решением UDT.

Вы можете использовать сочетание этих методов. Предположим, вам нужен класс, потому что у вас есть определенные поведения и вычисления, которые вы хотите включить вместе с данными. Вы можете использовать шаблон memento , чтобы удерживать состояние объекта внутри UDT:

Type MyMemento
    Value1 As Integer
    Value2 As String
End Type

В своем классе убедитесь, что все ваше внутреннее состояние хранится внутри частного члена типа MyMemento. Напишите свои свойства и методы, чтобы они использовали данные только в одной переменной частного члена.

Теперь сделать копию вашего объекта просто. Просто напишите новый метод в своем классе под названием Copy(), который возвращает новый экземпляр вашего класса и инициализирует его копией собственного memento:

Private Memento As MyMemento

Friend Sub SetMemento(NewMemento As MyMemento)
    Memento = NewMemento
End Sub

Public Function Copy() as MyClass
    Dim Result as MyClass
    Set Result = new MyClass
    Call Result.SetMemento(Memento)
    Set Copy = Result
End Function

Friend только скрывает его от материала вне вашего проекта, поэтому он мало чем скрывает SetMemento, но это все, что вы можете сделать с VB6.

HTH

36
ответ дан Scott Whitlock 27 August 2018 в 21:05
поделиться

или мне нужно скопировать объект по одному члену за раз ...

К сожалению, да.

Возможно (но технически очень very сложно) написать COM-сервер на C ++, который, используя интерфейс IDispatch, скопирует значение каждого свойства, но на самом деле это Программирование в высоком храме , если бы мне пришлось это сделать, я не знаю, мог ли я сделать это, но я бы посмотрел на что-то вроде 10-дневной работы ( и я знаю, как COM реализован на C ++, мне также необходимо исследовать, есть ли в ATL-инфраструктуре что-нибудь, чтобы помочь и т. д.).

Я работал с Vb3, 4,5 и amp; 6 для чего-то вроде 10 лет (руки, 5 дней в неделю) и никогда не находили хорошего способа сделать это, помимо ручного внедрения шаблонов сериализации, таких как Mementos и Save & amp; Магазин, который действительно просто сводился к фантастическим способам копирования каждого участника, по одному за раз.

2
ответ дан Binary Worrier 27 August 2018 в 21:05
поделиться

@Scott Whitlock, я не смог заставить ваш код работать, но если он будет работать, это было бы здорово.

Я создал регулярный модуль, в который я помещал тип memment

Type MyMemento
    Value1 As Integer
    Value2 As String
End Type

Затем я создаю модуль класса MyClass с кодом

Private Memento As MyMemento

Friend Sub SetMemento(NewMemento As MyMemento)
        Memento = NewMemento
End Sub

Public Function Copy() as MyClass
    Dim Result as MyClass
    Set Result = new MyClass
    Result.SetMemento(Memento)
    Set Copy = Result
End Function

Наконец, я пытаюсь вызвать функцию копирования в другом регулярном модуле, таком как

Sub Pruebas()
    Dim Primero As MyClass, segundo As MyClass
    Set Primero = New MyClass
    Set segundo = New MyClass
    Set segundo = Primero.Copy
End Sub

Я получаю сообщение (под рисунком): Ошибка компиляции: El tipo de agumento de ByRef не совпадает

Вот изображение (не более 10 баллов, так вот ссылка): http: //i.stack.imgur.com/KPdBR.gif

Я не смог получить сообщение на английском языке, я живу в Испании.

Не могли бы вы так любезно предоставить пример в VBA Excel ?, я действительно пытался сделать эту работу.

Спасибо за вашу работу

========== ==============================================================================================================================================

Проблема была в строке «Result.SetMemento (Memento)», в VBA ее нужно было вызвать с помощью «Call»

Public Function Copy() As MyClass
    Dim Result As MyClass
    Set Result = New MyClass
    Call Result.SetMemento(Memento)
    Set Copy = Result
End Function

Это отлично работает, спасибо Скотту Уитлоку, ты гений

3
ответ дан verzulsan 27 August 2018 в 21:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: