VB.NET Structs and Nothing - проблемы

У меня проблемы с использованием структур и функций, которые ничего не возвращают в VB.NET.

Позвольте мне попытаться объяснить здесь с помощью этого кода:

Public Class Form1
    Structure Test
        Dim field1 As String
    End Structure

    Private Function Foo() As Test
        Return Nothing
    End Function

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim st As Test = Foo()
    End Sub
End Class

В предыдущем коде, когда я возвращаю Nothing в результате функции Foo, я ожидал, что st равно Nothing. Но этого не происходит.

Затем я нашел в документации MSDN:

Если присвоить переменной Nothing значение по умолчанию для ее объявленного типа. Если этот тип содержит элементы-переменные, все они имеют значения по умолчанию.

Итак, я обнаружил, что когда я присваиваю структуре Nothing, все ее элементы устанавливаются в значения по умолчанию, а не сама структура.

Кроме того, я попытался сделать тип st допускающим значение NULL, объявив:

    Dim st As Nullable(Of Test) = Foo()  

но, тем не менее, я не могу проверить, равно ли st Ничего, используя:

    If st Is Nothing Then  

or

    If st.Equals(Nothing) Then

Итак, вопросы:
1 - Можно ли назначить Ничего структуре, а не ее членам?
2 - Как я могу проверить, является ли возвращаемое значение структуры Ничего ?


person RHaguiuda    schedule 02.07.2010    source источник
comment
См. Также stackoverflow.com/questions/5869661/   -  person jeroenh    schedule 25.04.2014


Ответы (3)


Структура - это тип значения, она не может быть Ничто. Тип Nullable может решить вашу проблему, поставьте вопросительный знак после имени типа, чтобы сделать его коротким и быстрым. Вот пример:

Module Module1

    Structure Test
        Dim field1 As String
    End Structure

    Private Function Foo() As Test?
        Return Nothing
    End Function

    Sub Main()
        Dim st As Test? = Foo()
        Debug.Assert(st is Nothing)
    End Sub

End Module
person Hans Passant    schedule 02.07.2010
comment
? является сокращением для Nullable(Of Test). - person AMissico; 03.07.2010
comment
@Hans Passant: Да уж, ты обманываешь. Мой ответ намного лучше! : O) - person AMissico; 03.07.2010
comment
Извините @amiss, это своего рода вопрос, когда просто добавьте вопросительный знак и передайте OP решение. Несомненно, ваш подробный ответ получит гораздо больше голосов, чем мой, в течение следующих 10 лет. Лучше проверьте эту теорию IsEmpty. - person Hans Passant; 03.07.2010
comment
@Hans Passant: Можете ли вы перейти к stackoverflow.com/questions/3169102/, и сделать комментарий относительно назначение временной переменной перед вызовом Invoke и почему это хорошая идея. Из предыдущего нашего обмена мнениями несколько недель назад я сделал технически некорректный комментарий, который вызвал шквал других комментариев. - person AMissico; 03.07.2010
comment
@AMissico: dtb прав, копия ссылки уже была сделана. То же, что и копирование в handler. Использование шаблона манипулятора является стандартным, пока яйцо не будет приготовлено таким же образом. - person Hans Passant; 03.07.2010
comment
@Hans Passant: Ах, я забыл, что куратор уже назначен. Спасибо. - person AMissico; 03.07.2010

Первые два следующих метода часто используются в .NET Framework. Используемый вами метод будет зависеть от ваших требований. Я воспользуюсь методом №3, если конструкция проверяется нечасто. Для частого тестирования я буду использовать метод №1, если метод №2 не подходит для «пустого» тестирования. Например, структура Point определяет пустую точку как {x = 0, y = 0}, что я не считаю правильным. Поэтому я бы использовал первый метод в моей реализации точечной структуры.

Метод 1. Определите Empty тест для сравнительного тестирования

Добавьте общий Test для использования при пустом сравнении.

Structure Test
    Public Shared Empty As Test = New Test
    Dim field1 As String 
End Structure 

Тестировать как:

If st = Test.Empty Then

Метод 2: определение свойства IsEmpty для тестирования

Определите свойство IsEmpty на основе внутреннего состояния структуры.

Structure Test 
    Public ReadOnly Property IsEmpty As Boolean
        Get
            Return Len(field1) = 0
        End Get
    End Property
    Dim field1 As String 
End Structure 

Тестировать как:

If st.IsEmpty Then

Метод 3: используйте Nullable (Of T)

Определить как:

Dim st As Test? = Foo() 
'--or--
Dim st As Nullable(Of Test) = Foo()

Тестировать как:

If st Is Nothing Then
'--or--
If st.HasValue = False Then

Примечание

Я не тестировал приведенный выше код, и у меня нет доступа к моей кодовой библиотеке.

Вдохновение

Взгляните на структуры Microsoft Point и Color, используя их опубликованный исходный код или используя .NET Reflector.

person AMissico    schedule 02.07.2010
comment
Ваш первый метод требует перегрузки оператора '=' для структуры. - person prabhakaran; 12.12.2011

Нет такой концепции, как присвоение «ничего структуре, но не ее членам».

Похоже, вы должны смотреть на типы значений, допускающие значение NULL и Nullable(Of T) - если вам нужно представить отсутствие «реальное» значение для типа значения, это в точности причина его изобретения.

Рассмотрим, например, Byte. Значение Byte может иметь любое из 256 значений (0–255). Если вы присвоите ему значение Nothing, это фактически сделает его 0. Он не может сделать его «некоторым значением не в диапазоне 0–255», поскольку оно будет сохранено как байт. Я считаю несколько прискорбным, что VB действительно позволяет вам использовать здесь Nothing, на самом деле ... потому что с философской точки зрения "отсутствующее" значение и значение 0 действительно очень разные вещи.

В любом случае, типы значений, допускающие значение NULL, заключают в оболочку "нормальные" типы значений и предоставляют дополнительное логическое значение, чтобы сказать, существует ли действительно полезное значение или нет.

person Jon Skeet    schedule 02.07.2010