Я собираюсь не согласиться с тенденцией здесь. Я сделаю запись:
Я не согласен с тем, что DBNull
служит какой-либо полезной цели; это вносит ненужную путаницу, но практически не приносит пользы.
Часто выдвигается аргумент, что null
— недопустимая ссылка, а DBNull
— шаблон нулевого объекта; ни одно из них не верно. Например:
int? x = null;
это не "неверная ссылка"; это значение null
. Действительно, null
означает все, что вы хотите, и, честно говоря, у меня нет абсолютно никаких проблем с работой со значениями, которые могут быть null
(действительно, даже в SQL нам нужно правильно работать с null
- здесь ничего не меняется). Точно так же «шаблон нулевого объекта» имеет смысл только в том случае, если вы на самом деле рассматриваете его как объект в терминах ООП, но если у нас есть значение, которое может быть «нашим значением или DBNull
», тогда оно должно быть object
, поэтому мы можем не делайте с ним ничего полезного.
С DBNull
так много плохого:
- это заставляет вас работать с
object
, так как только object
может содержать DBNull
или другое значение
- нет реальной разницы между "может быть значением или
DBNull
" и "может быть значением или null
"
- аргумент, что это происходит из 1.1 (pre-nullable-types), бессмысленен; мы могли бы прекрасно использовать
null
в 1.1
- у большинства API есть «это нуль?» методы, например
DBDataReader.IsDBNull
или DataRow.IsNull
- ни один из них на самом деле не требует существования DBNull
с точки зрения API
DBNull
терпит неудачу с точки зрения объединения с нулевым значением; value ?? defaultValue
не работает, если значение равно DBNull
DBNull.Value
нельзя использовать в необязательных параметрах, так как это не константа
- семантика времени выполнения
DBNull
идентична семантике null
; в частности, DBNull
на самом деле равно DBNull
, поэтому оно не выполняет работу по представлению семантики SQL
- он часто принудительно упаковывает значения типа значения, поскольку он чрезмерно использует
object
- если вам нужно проверить на
DBNull
, вы могли бы также протестировать только на null
- это вызывает огромные проблемы для таких вещей, как параметры команды, с очень глупым поведением, что если параметр имеет значение
null
, он не отправляется... ну, вот идея: если вы не хотите, чтобы параметр был отправлен - не добавлять его в коллекцию параметров
- каждая ORM, о которой я могу думать, отлично работает без какой-либо потребности или использования
DBNull
, за исключением дополнительной неприятности при общении с кодом ADO.NET.
Единственный даже отдаленно убедительный аргумент, который я когда-либо видел для оправдания существования такого значения, находится в DataTable
, при передаче значений для создания новый ряд; null
означает "использовать значение по умолчанию", DBNull
явно является нулем - честно говоря, этот API мог бы иметь особую обработку для этого случая - например, воображаемый DataRow.DefaultValue
был бы намного лучше, чем ввод DBNull.Value
, который заражает обширные участки кода бесплатно. причина.
Точно так же сценарий ExecuteScalar
... в лучшем случае незначителен; если вы выполняете скалярный метод, вы ожидаете результата. В сценарии, где строк нет, возврат null
не кажется таким уж ужасным. Если вам абсолютно необходимо устранить неоднозначность между «нет строк» и «возвращается один единственный нуль», есть API-интерфейс для чтения.
Этот корабль уже давно уплыл, и слишком поздно его чинить. Но! Пожалуйста, не думайте, что все согласны с тем, что это "очевидно". Многие разработчики не видят ценность в этой странной морщинке в BCL.
Мне на самом деле интересно, связано ли все это с двумя вещами:
- необходимость использовать слово
Nothing
вместо чего-то, включающего "null" в VB
- имея возможность использовать синтаксис
if(value is DBNull)
, который «выглядит точно так же, как SQL», а не такой хитрый if(value==null)
Резюме:
Наличие 3 вариантов (null
, DBNull
или фактическое значение) полезно только в том случае, если есть подлинный пример, в котором вам нужно устранить неоднозначность между 3 разными случаями. Мне еще предстоит увидеть случай, когда мне нужно представить два разных «нулевых» состояния, поэтому DBNull
совершенно избыточен, учитывая, что null
уже существует и имеет гораздо лучшую поддержку языка и среды выполнения.
person
Marc Gravell
schedule
09.03.2012
DBNull
предшествует введению в .NET framework подлинных типов, допускающих значение NULL. Оба ведут себя немного иначе, поэтомуDBNull
пришлось остаться (к моему сожалению, но это уже другая история). - person Jeroen Wiert Pluimers   schedule 09.03.2013