el objeto nullable debe tener un valor


Hay una paradoja en la descripción de la excepción: El objeto nullable debe tener un valor (?!)

Este es el problema:

Tengo una clase DateTimeExtended , que tiene

{
  DateTime? MyDataTime;
  int? otherdata;

}

Y un constructor

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

Ejecutando este código

DateTimeExtended res = new DateTimeExtended(oldDTE);

Lanza un InvalidOperationException con el mensaje:

El objeto nullable debe tener un valor.

myNewDT.MyDateTime.Value - es válido y contiene un objeto regular DateTime.

¿Cuál es el significado de este mensaje y qué soy yo haciendo mal?

Tenga en cuenta que oldDTE no es null. He eliminado el Value de myNewDT.MyDateTime pero la misma excepción se lanza debido a un setter generado.

Author: The Red Pea, 2009-12-13

7 answers

Debe cambiar la línea this.MyDateTime = myNewDT.MyDateTime.Value; a solo this.MyDateTime = myNewDT.MyDateTime;

La excepción que estaba recibiendo fue arrojada en el .Value propiedad de la Nullable DateTime, como se requiere devolver un DateTime (ya que eso es lo que establece el contrato para .Value), pero no puede hacerlo porque no hay DateTime que devolver, por lo que lanza una excepción.

En general, es una mala idea llamar ciegamente a .Value en un tipo nullable, a menos que tenga algún conocimiento previo de que esa variable DEBE contener un valor (es decir, a través de un .HasValue check).

EDITAR

Aquí está el código para DateTimeExtended que no arroja una excepción:

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

    public DateTimeExtended() { }

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

Lo probé así: {[15]]}

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

Agregar el .Value en other.MyDateTime causa una excepción. Eliminarlo elimina la excepción. Creo que estás buscando en el lugar equivocado.

 158
Author: Yuliy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-14 09:59:52

Intenta soltar el .valor

 5
Author: Paul Creasey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-12-13 11:12:30

Cuando se utilizan métodos de extensión LINQ (p. ej. Select, Where), la función lambda puede ser convertida a SQL que puede no comportarse de manera idéntica a su código C#. Por ejemplo, los cortocircuitos de C#evaluados || y && se convierten en eager AND y OR de SQL. Esto puede causar problemas cuando usted está buscando null en su lambda.

Ejemplo:

MyEnum? type = null;
Entities.Table.Where(a => type == null || 
    a.type == (int)type).ToArray();  // Exception: Nullable object must have a value
 4
Author: Protector one,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-01-21 13:23:23

En este caso oldDTE es null, por lo que cuando intenta acceder a oldDTE.Valor la InvalidOperationException se lanza ya que no hay valor. En tu ejemplo simplemente puedes hacer:

this.MyDateTime = newDT.MyDateTime;
 2
Author: Lee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-12-13 11:13:32

Asigna los miembros directamente sin la parte .Value:

DateTimeExtended(DateTimeExtended myNewDT)
{
   this.MyDateTime = myNewDT.MyDateTime;
   this.otherdata = myNewDT.otherdata;
}
 1
Author: Cecil Has a Name,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-12-13 11:13:25

Se parece a oldDTE.myDateTime era nulo, por lo que constructor trató de tomar su Valor-que arrojó.

 0
Author: Pavel Radzivilovsky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-12-13 11:14:43

Recibí este mensaje al intentar acceder a los valores de un objeto con valor nulo.

sName = myObj.Name;

Esto producirá un error. Primero debe comprobar si el objeto no es null

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

Esto funciona.

 0
Author: Juris,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-09-28 13:19:36