Торговый оператор VB VS C #: зачем ничего не решает нулю?

StackOverflow https://stackoverflow.com/questions/4147277

Вопрос

Я просто снимаю себя в ногу и хотел бы знать, были ли фактические причины сделать эту ситуацию возможной.
И в любом случае этот вопрос может остаться на удобство будущих стрелков для ног.


Предположим, у нас есть оттудаваемое значение в 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 имеет в типе целое число?

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top