2009-12-13 20 views
144

No es paradoja en la descripción de excepción: objeto anulable debe tener un valorobjeto anulable 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; 
} 

ejecutar este código

DateTimeExtended res = new DateTimeExtended(oldDTE); 

emite una InvalidOperationException con el mensaje:

objeto anulable debe tener un valor.

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

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

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

+0

¿Cuál es el otro constructor? –

+0

Extraño. Reproduzco la excepción con .Value allí, y no obtengo ninguna excepción sin el .Value allí. ¿Seguro que estás ejecutando el código actualizado? – Yuliy

+0

El constructor toma una instancia de sí mismo. ¿Cómo estás creando esa primera instancia? –

Respuesta

147

debe cambiar la línea de this.MyDateTime = myNewDT.MyDateTime.Value; sólo this.MyDateTime = myNewDT.MyDateTime;

La excepción que estaba recibiendo fue arrojado en el .Value propiedad del anulableDateTime, ya que es necesario devolver un DateTime (ya que eso es lo que indica el contrato para .Value), pero no puede hacerlo porque no hay DateTime que devolver, por lo que arroja una excepción.

En general, es una mala idea llamar a ciegas .Value en un tipo anulable, a menos que tenga algún conocimiento previo de que esa variable MUST contienen un valor (es decir, a través de un cheque .HasValue).

EDITAR

Aquí está el código para DateTimeExtended que no lanza 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; 
    } 
} 

he comprobado como esto:

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

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

+0

Tiene razón acerca del valor., Pero hay algo más que causa la excepción. He eliminado el valor. He cambiado el orden de los códigos del constructor, primero copiando el valor int, pero se lanza la misma excepción. – Dani

+0

He comentado sobre la pregunta: encontré el problema, estaba en un setter generado para las propiedades. – Dani

+0

sí, resolvió mi problema, simplemente cambio el objeto capaz de nulo a no nulo y convierto datetime a cadena directamente, no por fechahoraobjeto.valor.datetime.tostring() – adnan

4

intente poner el .value

+0

no ayuda. arroja la misma excepción si primero corro la segunda línea. – Dani

1

Asignar los miembros directamente sin la parte .Value:

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

En este caso oldDTE es nula, por lo que cuando se intenta acceder a la oldDTE.Value InvalidOperationException se lanza desde no hay valor En su ejemplo puede simplemente hacer:

this.MyDateTime = newDT.MyDateTime; 
+0

El oldDTE no es nulo, pero eliminé el valor de todos modos ... todavía está lanzando esa excepción .... – Dani

0

Parece que oldDTE.MyDateTime era nulo, por lo que el constructor intentó tomar su valor, que arrojó.

0

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

sName = myObj.Name; 

Esto producirá un error. Primero debe verificar si el objeto no es nulo

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

Esto funciona.

+0

Antes de responder, intente leer primero las demás respuestas a la pregunta, especialmente la respuesta aceptada que dice exactamente lo que usted colocó en * su * respuesta. Aunque no lo muestra usando código, lo deletrea. Además, intente hacer que su código de ejemplo sea relevante para la pregunta, como 'this.MyDateTime = myNewDT.MyDateTime.Value;', not 'sName = myObj.Name;' – newfurniturey

2

Al usar métodos de extensión LINQ (por ejemplo, Select, Where), la función lambda podría convertirse a SQL que podría no comportarse de manera idéntica a su código C#. Por ejemplo, el cortocircuito de C# evaluado || y && se convierten a los ansiosos AND y OR de SQL. Esto puede causar problemas cuando está buscando nulo 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 
+0

Me doy cuenta de que esta respuesta no es relevante para el caso específico del OP. , pero es relevante para la Excepción que está recibiendo. Además, esta página es el primer hit en Google para esa excepción, lo que la hace relevante. –

Cuestiones relacionadas