Ответ 1
В VB 9.0 "IF" - истинная операция коалесценции, эквивалентная С# "??". Источник MSDN:
Итак, вы можете использовать:
oObject.Name = IF(oReader.Item("Name").Equals(DBNull.Value),string.Empty,DirectCast(oReader.Item("Name"), String))
Большая часть нашей разработки выполняется в vb.net(а не на моем выборе), и один часто используемый шаблон кода использует "On Error GoTo", за которым следует "Продолжить", чтобы все поля базы данных можно было читать с помощью DirectCast ( ) и любые значения DBNull просто игнорируются.
Текущий код будет
On Error GoTo error_code
oObject.Name = DirectCast(oReader.Item("Name"), String)
oObject.Value = DirectCast(oReader.Item("Value"), Integer)
error_code:
Resume Next
Код С#, чтобы заменить это, включить удаление кода On Error будет
oObject.Name = oReader["Name"] as string ?? string.Empty;
oObject.Value = oReader["Value"] as int? ?? -1;
Проблема заключается в том, что ebivelent vb.net этого С# -кода использует TryCast(), который может использоваться только для ссылочных типов (типы с нулевым значением - типы значений), в то время как ключевое слово С# как ключевое слово может использоваться для ссылочных и нулевых типов.
Итак, у кого-нибудь есть пример кода vb.net, который делает то же самое, что и код С# в одной строке в поле базы данных?
-Edit -
Я решил, что я считаю лучшим решением в нашем случае. Методы помощников не подходят (из-за управления), и мы не можем использовать методы расширения, так как мы используем только .NET 2.0 (хотя с VS 2008, поэтому мы получаем If())
oObject.Name = If(oReader.IsDBNull(oReader.GetOrdinal("Name")), String.Empty, oReader.GetString(oReader.GetOrdinal("Name")))
oObject.Value = If(oReader.IsDBNull(oReader.GetOrdinal("Value")), 0, oReader.GetInt32(oReader.GetOrdinal("Value")))
В VB 9.0 "IF" - истинная операция коалесценции, эквивалентная С# "??". Источник MSDN:
Итак, вы можете использовать:
oObject.Name = IF(oReader.Item("Name").Equals(DBNull.Value),string.Empty,DirectCast(oReader.Item("Name"), String))
Извините за прорастание такой чепухи. Я полагался на публикацию публикации Пола Вика (тогда глава команды VB), а не MSDN и не установлены Windows для проверки кода.
Я по-прежнему оставляю свою публикацию - сильно изменен (обратитесь к истории изменений, чтобы прочитать неправильный оригинальный текст) - потому что я нахожу, что у пунктов все еще есть некоторые достоинства.
Итак, еще раз, три вещи, которые нужно повторить:
Для ссылочных типов, С# as
непосредственно моделируется TryCast
в VB.
Тем не менее, С# добавляет немного дополнительных для обработки типов значений через unboxing (а именно, возможности для типов типов unbox для их сопоставления Nullable
через as
).
VB 9 предоставляет оператор If
для реализации двух различных операторов С#: null
coalescing (??
) и условного (?:
), как показано ниже:
' Null coalescing: '
Dim result = If(value_or_null, default_value)
' Conditional operator: '
Dim result = If(condition, true_value, false_value)
В отличие от предыдущей функции IIf
это настоящие короткозамкнутые операторы, т.е. будет выполнена только необходимая часть. В частности, следующий код будет компилироваться и выполняться просто отлично (он не будет с функцией IIf
, так как мы могли бы делить на ноль):
Dim divisor = Integer.Parse(Console.ReadLine())
Dim result = If(divisor = 0, -1, 1 \ divisor)
On Error GoTo …
или On Error Resume [Next]
). Это обратная совместимость для простого преобразования VB6. Вместо этого используйте механизмы обработки исключений .NET, как в С#.Используйте метод IsDbNull
для проверки нулевых значений вместо дорогостоящего подхода с ошибкой при неудачной обработке. Обработка ошибок почти всегда дороже, чем ловить условие, прежде чем оно станет ошибкой.
(Кроме того, обработка ошибок должна использовать исключения, а не стиль VB6 ON ERROR GOTO HELL...)
С условной If
функцией, которая будет выглядеть как однострочный:
oObject.Name = If(oReader.IsDbNull(oReader.GetOrdinal("Name")), Nothing, oReader.GetString(oReader.GetOrdinal("Name")))
Я бы предпочел написать некоторые вспомогательные функции, которые могли бы использоваться, чтобы сделать код более читаемым и более эффективным:
Function GetStringOrDefault(reader As DbDataReader, key As String) As String
Dim ordinal = reader.GetOrdinal(key)
If reader.IsDbNull(ordinal) Then
Return Nothing
Else
Return reader.GetString(ordinal)
End If
End Function
Использование:
oObject.Name = GetStringOrDefault(oReader, "Name")
Вместо этого вы можете записать их как расширения класса DbDataReader
, чтобы сделать их еще более удобочитаемыми.
Я не думаю, что у VB.NET есть оператор, который имитирует работу оператора ??
С#. Тем не менее, вы можете использовать эквивалент тернарного оператора С# - Функция IIF в вашем случае:
Допустимо уродливый:
oObject.Name = IIf(oReader.Item("Name").Equals(DBNull.Value), DirectCast(oReader.Item("Name"), String), String.Empty)
oObject.Value = IIf(oReader.Item("Value").Equals(DBNull.Value), DirectCast(oReader.Item("Value"), Integer), -1)
Пожалуйста, не забудьте прочитать пост Стивена Уэтерфорда в приведенной выше ссылке, в которой предлагается общая функция IIf, которая запрашивает требования типа из предоставленных аргументов. Это становится необходимым, потому что функция IIf всегда возвращает объект!
Лучшим вариантом было бы создание функции, выполняющей этот листинг условно, вместо того, чтобы пытаться сделать это в одной строке.
Все добавили некоторые важные аргументы в эту дискуссию, поэтому я подумал, что обобщил бы важные моменты.
VB.net TryCast() НЕ совпадает с ключевым словом С#. Если бы это было то же самое, тогда не было бы необходимости в этом вопросе в первую очередь.
VB.net использует функцию If() для тройных операций и операций нулевой коалесценции. Это не так легко читать, как версия С# (? И уважительно). Попытайтесь избежать функции vb.net IIf(), поскольку это не то же самое.
Шаблон коллаборации с нулевым коалесцентом не работает, поскольку мы не можем использовать TryCast() с нулевыми типами, поэтому мы должны использовать тройственный шаблон.
oReader.IsDBNull(oReader.GetOrdinal( "Имя" )) - лучший способ проверить, является ли значение DBNull.
В соответствии с документами TryCast работает только со ссылочными типами. Независимо от того, что проблема может быть связана с использованием вами IDataReader, чем с запросом.
Прежде чем перебирать строки в IDataReader, получите порядковые значения имен столбцов и используйте строго типизированные методы GetX для получения значений полей таким образом
Dim name As Integer = oReader.GetOrdinal("Name")
Dim value as Integer = oReader.GetOrdinal("Value")
While reader.Read()
oObject.Name = if(oReader.IsDbNull(name), string.Empty, oReader.GetString(name))
oObject.Value = if(oReader.IsDbNull(value), -1, oReader.GetInt32(value)
End While
' Call Close when done reading.
oReader.Close()
Используя оператор if с тремя параметрами, подобными этому, он работает так же, как термальный логический оператор С# eval? trueExpression: falseExpression
Это поможет вам в решении проблемы.