2009-03-27 2 views
33

Почему не разрешено присваивать значение null DateTime в C#? Как это было реализовано? И можно ли использовать эту функцию, чтобы сделать ваши собственные классы недействительными?Почему для DateTime в C# допустимо значение null?

Пример:

string stringTest = null; // Okay 
DateTime dateTimeTest = null; // Compile error 

Я знаю, что я могу использовать DateTime? в C# 2.0, чтобы нулевой быть назначен dateTimeTest и что я мог бы использовать Jon Skeet's NonNullable class на моей строке, чтобы получить ошибку во время выполнения программы по заданию stringTest. Мне просто интересно, почему два типа ведут себя по-другому.

+0

Это Джон, а не Джон. –

ответ

76

DateTime - это значение типа (struct), где-строка является ссылочным типом (class и т. Д.). Это ключевое различие. Ссылка всегда может быть нулевой; значение не может (если оно не использует Nullable<T> - то есть DateTime?), хотя оно может быть нулевым (DateTime.MinValue), которое часто интерпретируется как то же, что и значение null (особенно в 1.1).

+0

Большое спасибо за разъяснение. Почему бы не использовать structs для создания классов, не допускающих null? –

+1

А что будет по умолчанию (YourWrapper)? ; -p Это будет структура, содержащая нулевую ссылку ... все структуры * всегда * имеют конструктор по умолчанию ... –

+0

(или * never * имеют конструктор по умолчанию, в зависимости от того, говоришь ли вы о C# или CLI - которые не согласны с этим моментом) –

8

DateTime - это структура, а не класс. Сделайте «перейти к определению» или просмотрите его в обозревателе объектов, чтобы увидеть.

HTH!

1

DateTime - тип значения, такой же, как и int. Только ссылочные типы (например, string или MyCustomObject) могут быть пустыми. Типы ссылок действительно хранят «ссылки» на местоположение объектов в куче.

вот article Я нашел, что объясняет это лучше. и здесь есть MSDN article on it

+0

Или типы NULL-значений через Nullable (который сам по себе также является структурой) –

0

Строка - это класс, тогда как DateTime - это структура. Вот почему вы не можете установить его в null

7

Важное различие между ValueTypes и ссылочными типами состоит в том, что типы значений имеют эту «семантику значений». DateTime, Int32 и все другие типы значений не имеют идентификатора, Int32 «42» по существу неотличим от любого другого Int32 с тем же значением.

Все типы значений «объекты» существуют либо в стеке, либо как часть объекта ссылочного типа. Одним из особых случаев является то, что экземпляр типа значения присваивается объекту или интерфейсу - это называется «бокс», и он просто создает объект фиктивного ссылочного типа, который содержит только значение, которое можно извлечь обратно («unboxed») ,

С другой стороны, типы ссылок имеют личность. «новый объект()» не равен никакому другому «новому объекту()», поскольку они представляют собой отдельные экземпляры в куче GC. Некоторые ссылочные типы предоставляют метод Equals и перегруженные операторы, так что они ведут себя более ценно, например, например. Строка «abc» равна другой строке «abc», даже если они фактически являются двумя разными объектами.

Поэтому, когда у вас есть ссылка, он может содержать адрес действительного объекта или может быть нулевым. Когда объекты типа значения все-ноль, они просто равны нулю. Например. целое число 0, ноль с плавающей точкой, логическое значение false или DateTime.MinValue. Если вам нужно различать «ноль» и «значение missing/null», вам нужно использовать либо отдельный логический флаг, либо, еще лучше, использовать класс Nullable < T> в .NET 2.0. Это просто значение плюс флаг Boolean. В CLR также поддерживается поддержка, так что бокс Nullable с HasValue = false приводит к нулевой ссылке, а не в коробке с ложным + нолем, как если бы вы сами реализовали эту структуру.

1

Для значения типа null должно быть какое-то значение, которое может содержать какое-либо другое законное значение, а , которое система каким-то образом будет знать, должно рассматриваться как «null». Некоторые типы значений могут соответствовать первому критерию, не требуя дополнительного хранения. Если .net был разработан с нуля с концепцией обнуляемых ценностей в виде, это могло быть Object include a virtual IsLogicalNull property, and a non-virtual IsNull which would return правдой if это is null and, otherwise invoke its IsLogicalNull property and return the result. If .net had done this, it would have avoided the need for the quirky boxing behavior and структуры constraint of Nullable (an empty Nullable could be boxed as an empty Nullable , and still be recognized as null`).

К тому времени, было принято решение обеспечить поддержку обнуляемого типов значений в .NET 2.0, однако, много кода было написано, который предположил, что значения по умолчанию для таких вещей, как Guid и DateTime не будет рассматриваться как null. Поскольку значительная часть значений в типах с нулевым значением лежит с их предсказуемым значением по умолчанию (то есть null), имеющим типы, которые имеют значение null, но по умолчанию не соответствует чему-либо другому, добавило бы больше путаницы, чем значение.

Смежные вопросы