обнуляемый объект должен иметь значение


190

В описании исключения есть парадокс: обнуляемый объект должен иметь значение (?!)

Это проблема:

У меня есть DateTimeExtendedкласс, который имеет

{
  DateTime? MyDataTime;
  int? otherdata;

}

и конструктор

DateTimeExtended(DateTimeExtended myNewDT)
{
   this.MyDateTime = myNewDT.MyDateTime.Value;
   this.otherdata = myNewDT.otherdata;
}

работает этот код

DateTimeExtended res = new DateTimeExtended(oldDTE);

Кидает InvalidOperationExceptionс сообщением:

Обнуляемый объект должен иметь значение.

myNewDT.MyDateTime.Value- действителен и содержит обычный DateTimeобъект.

В чем смысл этого сообщения и что я делаю не так?

Обратите внимание, что oldDTEэто не так null. Я удалил Valueиз, myNewDT.MyDateTimeно то же исключение выдается из-за сгенерированного сеттера.


Какой другой конструктор?
— Пол Криси

Странный. Я воспроизвожу исключение с .Value там и не получу исключения без .Value там. Вы уверены, что используете обновленный код?
— Юлий

Конструктор берет экземпляр себя. как вы создаете этот первый экземпляр?
— Пол Криси

он создается как new () без параметров, а затем я добавляю значения (это работает).
— Дани

6
Проблема решена - проблема не была там ... был создан сгенерированный установщик для других данных и MyDateTime, который проверял значение перед его установкой .. летал, когда он нулевой !!!
— Дани

Ответы:


201

Вы должны изменить строку this.MyDateTime = myNewDT.MyDateTime.Value;простоthis.MyDateTime = myNewDT.MyDateTime;

Исключение, которое вы получили, было брошено в .Valueсобственность Nullable DateTime , так как требуется вернуть DateTime(поскольку это то, что является контрактом для .Valueгосударств), но это не может быть сделано, потому что нет DateTimeвозврата, поэтому оно выдает исключение.

В общем, плохая идея - слепо вызывать .Valueобнуляемый тип, если у вас нет предварительных знаний о том, что эта переменная ДОЛЖНА содержать значение (т. Е. Посредством .HasValueпроверки).

РЕДАКТИРОВАТЬ

Вот код для DateTimeExtendedэтого не исключение:

class DateTimeExtended
{
    public DateTime? MyDateTime;
    public int? otherdata;

    public DateTimeExtended() { }

    public DateTimeExtended(DateTimeExtended other)
    {
        this.MyDateTime = other.MyDateTime;
        this.otherdata = other.otherdata;
    }
}

Я проверил это так:

DateTimeExtended dt1 = new DateTimeExtended();
DateTimeExtended dt2 = new DateTimeExtended(dt1);

Добавление .Valueon other.MyDateTimeвызывает исключение. Удаление этого избавляет от исключения. Я думаю, что вы смотрите не в том месте.


Вы правы насчет .value, но что-то еще вызывает исключение. Я удалил .value и изменил порядок кода конструктора, сначала скопировав значение int, но выдается то же исключение.
— Дани

Я прокомментировал вопрос - нашел проблему, это было в сгенерированном сеттере для свойств.
— Дани

да, это решило мою проблему, я просто изменил нулевой способный объект на ненулевой, и преобразовал datetime в строку напрямую, а не datetimeobject.value.datetime.tostring ()
— adnan

Отличный ответ. Получение исключения .Valueдля нулевого объекта имеет смысл (я полагаю), но сообщение об исключении действительно вводит в заблуждение, если вы имеете дело с двумя объектами Nullable. Что-то вроде «Свойство .Value требует, чтобы объект был ненулевым», имело бы намного больше смысла.
— ДВК,

9

При использовании методов расширения LINQ (например Select, Where) лямбда-функция может быть преобразована в SQL, который может вести себя не так, как ваш код C #. Так , например, короткое замыкание оценивали С # &&и ||преобразуются в SQL, стремятся ANDи OR. Это может вызвать проблемы, когда вы проверяете ноль в своей лямбде.

Пример:

MyEnum? type = null;
Entities.Table.Where(a => type == null || 
    a.type == (int)type).ToArray();  // Exception: Nullable object must have a value

5
Я понимаю, что этот ответ не имеет отношения к конкретному случаю ОП, но он относится к исключению, которое он получает. Кроме того, эта страница является первым попаданием в Google для этого исключения, что делает ее актуальной.
— Один защитник

6

Попробуйте сбросить .value

DateTimeExtended(DateTimeExtended myNewDT)
{
   this.MyDateTime = myNewDT.MyDateTime;
   this.otherdata = myNewDT.otherdata;
}

не помогает выдает то же исключение, если я запускаю вторую строку первой.
— Дани

2

В этом случае oldDTE имеет значение null, поэтому при попытке доступа к oldDTE.Value генерируется исключение InvalidOperationException, поскольку значение отсутствует. В вашем примере вы можете просто сделать:

this.MyDateTime = newDT.MyDateTime;

OldDTE не является нулевым, но я все равно удалил значение ... он все еще выбрасывает это исключение ....
— Dani

1

Назначьте участников напрямую без .Valueчасти:

DateTimeExtended(DateTimeExtended myNewDT)
{
   this.MyDateTime = myNewDT.MyDateTime;
   this.otherdata = myNewDT.otherdata;
}


0

Я получил это сообщение при попытке получить доступ к значениям объекта с нулевым значением.

sName = myObj.Name;

это приведет к ошибке. Сначала вы должны проверить, если объект не нулевой

if(myObj != null)
  sName = myObj.Name;

Это работает.


1
Прежде чем ответить, попробуйте сначала прочитать другие ответы на вопрос - особенно принятый ответ, в котором точно указано, что вы указали в своем ответе. Хотя он не показывает это с помощью кода, он разъясняет это. Кроме того, попробуйте сделать свой пример кода соответствующим для вопроса - например this.MyDateTime = myNewDT.MyDateTime.Value;, нетsName = myObj.Name;
— newfurniturey

0

Я получил это решение, и оно работает на меня

if (myNewDT.MyDateTime == null)
{
   myNewDT.MyDateTime = DateTime.Now();
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.