Торговый оператор VB VS C #: зачем ничего не решает нулю?
-
30-09-2019 - |
Вопрос
Я просто снимаю себя в ногу и хотел бы знать, были ли фактические причины сделать эту ситуацию возможной.
И в любом случае этот вопрос может остаться на удобство будущих стрелков для ног.
Предположим, у нас есть оттудаваемое значение в vb.net:
Dim i as Integer?
Мы хотим присваивать значение для него, основываясь на условиях и используя тройной оператор, потому что это так аккуратно и прочее:
i = If(condition(), Nothing, 42)
То есть, если условие true
, Используйте Nullability, в противном случае значение.
В этот момент возникает стрельба. Без очевидной причины компилятор VB-компиляции решает, что общий базовый тип для Nothing
а также Integer
является Integer
, в этот момент он молча переводит утверждение:
i = If(condition(), 0, 42)
Теперь, если вы должны были сделать это в C #:
i = (condition()) ? null : 42;
Вы немедленно получите ошибку компилятора, сказав, что <null>
не смешивается хорошо с int
. Отказ Что отлично, так как моя нога была бы здоровее, я бы пошел C # путь на этот раз. И для этого скомпилировать, вы должны явно написать:
i = (condition()) ? null : (int?)42;
Теперь ваша очередь могу Сделайте то же самое в VB и получите правильный нуль-несс, вы ожидаете:
i = If(condition(), Nothing, CType(42, Integer?))
Но это требует, чтобы ваша нога выстрел в первую очередь. Там нет ошибки компилятора, и нет предупреждения. Это с Explicit On
а также Strict On
.
Так что мой вопрос, почему?
Должен ли я взять это как ошибку компилятора?
Или кто-то может объяснить, почему компилятор ведет себя таким образом?
Решение
Это потому что VB Nothing
не является прямым эквивалентом C # null
.
Например, в C # этот код не скомпилируется:
int i = null;
Но этот код VB.NET работает просто хорошо:
Dim i As Integer = Nothing
Vb.net's. Nothing
на самом деле более близкий матч для C # 'S default(T)
выражение.
Другие советы
Темнарный оператор может вернуть только один тип.
В C #, он пытается выбрать тип на основе null
а также 42
. Отказ Хорошо, null
не имеет типа, поэтому он решает, что возвратный тип тройного оператора является то, что 42
; простая старая int
. Отказ Тогда он жалуется, потому что вы не можете вернуть нулю как простю старого int
. Отказ Когда вы принудите 42 как int?
, Торговый оператор собирается вернуть int?
, так null
Действительно.
Теперь я не знаю о VB, но цитируя от MSDN,
Assigning Nothing to a variable sets it to the default value for its declared type.
Который, поскольку VB определяет, что Темнарный оператор вернет int
(используя тот же процесс C # сделал), Nothing
является 0
. Отказ Опять же, принуждение 42
быть АН int?
повороты Nothing
в значение по умолчанию int?
, который null
, как вы ожидали.
Я думаю, что это что-то больше, чем делать, чем с чем с ним. Рассмотрим этот код:
''# This raises an exception
Dim x As Integer?
x = If(True, Nothing, Nothing)
MessageBox.Show(x.Value)
''# As does
Dim x As Integer?
x = Nothing
MessageBox.Show(x.Value)
''# Changing one of the truthpart arguments of If is what seems to return the zero.
Dim x As Integer?
x = If(True, Nothing, 5)
MessageBox.Show(x.Value)
Почему это делает это, я до сих пор не знаю, наверное, вопрос для команды VB. Я не думаю, что это связано с ним ключевым словом, либо NULLABLE.
Nothing
а также null
не то же самое ... от MSDN:
Назначение ничего для переменной, устанавливает его значение по умолчанию для его объявленного типа.
Также
Если вы поставляете тип значения в выражении, Isnothing всегда возвращает false.
Имейте в виду, что int? Звуковой тип, но это все еще тип значения, а не тип ссылки.
Попробуйте установить его DbNull.Value
вместо Nothing
...
В ряде случаев Nothing
будет преобразован в значение по умолчанию. Использовать Nothing
так же, как вы бы использовали null
Вам нужно бросить его на правильный нумерный тип.
Dim str As String
Dim int As Nullable(Of Integer) ' or use As Integer?
Dim reader As SqlDataReader
Dim colA As Integer = reader.GetOrdinal("colA")
Dim colB As Integer = reader.GetOrdinal("colB")
str = If(reader.IsDBNull(colA), DirectCast(Nothing, String), reader.GetString(colA))
int = If(reader.IsDBNull(colB), DirectCast(Nothing, Nullable(Of Integer)), reader.GetInt32(colB))
Это происходит, потому что целое число не является ссылочным типом. «Ничто» должно работать только для эталонных типов. Для типов ценностей, назначенные ничто, не автоматически преобразуется в значение по умолчанию, которое находится в случае целочисленного числа 0.
Это на самом деле возможно в VS2015 (по крайней мере), используя новое целое число?
Бывший.:
Если (TESTINT> 0, TESTINT, NEW INTEGER?), Где TestInt имеет в типе целое число?