Обнуляемая цепочка методов с ?-оператором

Я думал, что могу связать методы/свойства в Nullable Types, используя ?-оператор, например

Dim foo As SomeObject? = New SomeObject()
Dim bar As SomeObject? = Nothing
foo?.SomeProperty 'Returns a value
bar?.someProperty 'Returns Nothing

Однако на следующем частном примере

Structure Foo
  Public Sub New(bar As Integer)
    Me.Bar = bar
  End Sub
  Property Bar() As Integer
  Public Shared Operator +(f1 As Foo, f2 As Foo) As Foo
    Return New Foo(f1.Bar + f2.Bar)
  End Operator
End Structure

Я получаю сообщение об ошибке после выполнения следующей операции

Dim baz1 As Foo? = New Foo(13)
Dim baz2 As Foo? = New Foo(37)
Dim baz3 = baz1 + baz2
baz3?.Bar 'error BC36637: The '?' character cannot be used here

Почему это так и что более важно, как я могу добиться поведения, показанного в моем первом примере вверху?


person Tobi Holy    schedule 28.02.2017    source источник


Ответы (1)


Основная проблема после тестирования:

Я скопировал ваш точный код в VS2015 и протестировал его. Проблема в том, что вы пытаетесь вызвать свойство, но ничего с ним не делаете.

Вы не можете просто вызвать свойство. Вам нужно либо писать в него, либо читать из него. Ниже работает просто отлично.

Dim baz1 As Foo? = New Foo(13)
Dim baz2 As Foo? = New Foo(37)
Dim baz3 = baz1 + baz2

Dim fooBar = baz3?.Bar

Если я на самом деле добавлю метод, он тоже будет работать:

Dim baz1 As Foo? = New Foo(13)
Dim baz2 As Foo? = New Foo(37)
Dim baz3 = baz1 + baz2
baz3?.FooBar()

Фактическая ошибка, которую я получил с вашим кодом, была:

BC30545: Доступ к свойству должен быть назначен свойству или использовать его значение.

Старая мысль:

Проблема связана с перегрузкой вашего оператора +. Вы вернули стандартный экземпляр структуры. Это не обнуляется. Следовательно, вы не можете использовать оператор ?, так как он никогда не будет нулевым и не может быть нулевым.

Public Shared Operator +(f1 As Foo, f2 As Foo) As Foo
    Return New Foo(f1.Bar + f2.Bar)
End Operator

Возможно, вы сможете заставить его работать (непроверено), изменив свое объявление на:

Dim baz3 As Foo? = baz1 + baz2

Но даже тогда это может не сработать, потому что baz1+baz2 в настоящее время также никогда не будет нулевым.

person TyCobb    schedule 28.02.2017
comment
быстрая проверка типа с использованием TypeOf(baz3) ... показывает Foo? как фактический тип, и поэтому цепочка с символом ? должна работать, не так ли? - person Tobi Holy; 01.03.2017
comment
@no_mindset Я этого не вижу, потому что код, который вы показали, указанный как возврат для перегрузки вашего оператора, был As Foo. Это должно быть As Foo?, если вы хотите, чтобы он возвращал тип, допускающий значение NULL. Это может работать во время выполнения, но вы получаете ошибку во время компиляции. - person TyCobb; 01.03.2017
comment
даже если я объявлю возвращаемый тип перегрузки оператора As Foo?, произойдет та же ошибка; тип bar3 по-прежнему Foo? - person Tobi Holy; 01.03.2017
comment
@no_mindset обновил мой ответ после фактического тестирования вашего кода. - person TyCobb; 01.03.2017
comment
+1 ты, я принял ответ, потому что считаю, что ты прав, но даже присвоение свойства или вызов эквивалентного метода приводит к ошибке для меня, но я сильно полагаю, что должен винить свой компилятор в том, что он не является последней версией для поддержки символа ? в этом месте. не могли бы вы подтвердить свою версию vbc.exe для меня? мой 14.6.1586 - person Tobi Holy; 01.03.2017
comment
@no_mindset Это версия, которая у меня есть в моей папке .NET, но я не верю, что Visual Studio работает именно с ней, поскольку вам все еще нужна более новая версия VS, чтобы использовать более новый синтаксический сахар. Например, VS2013 не поддерживает C#6, хотя у меня также установлен VS2015. - person TyCobb; 01.03.2017
comment
Это должно быть проблемой, поскольку в настоящее время у меня нет установленного VS2015. Большое тебе спасибо! - person Tobi Holy; 01.03.2017