2009-12-13 3 views
144

Il y a paradoxe dans la description d'exception: objet Nullable doit avoir une valeurobjet nullable doit avoir une valeur

Ceci est le problème (?!):

J'ai une classe DateTimeExtended, qui a

{ 
    DateTime? MyDataTime; 
    int? otherdata; 

} 

et un constructeur

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

exécuter ce code

DateTimeExtended res = new DateTimeExtended(oldDTE); 

jette un InvalidOperationException avec le message:

objet Nullable doit avoir une valeur.

myNewDT.MyDateTime.Value - est valide et contient un objet DateTime normal.

Quelle est la signification de ce message et qu'est-ce que je fais de mal?

Notez que oldDTE n'est pas null. J'ai supprimé le Value de myNewDT.MyDateTime mais la même exception est levée en raison d'un setter généré.

+0

Quel est l'autre constructeur? –

+0

Étrange. Je reproduis l'exception avec le .Value là, et n'obtiens aucune exception sans le .Value là. Etes-vous sûr que vous utilisez le code mis à jour? – Yuliy

+0

Le constructeur prend une instance de lui-même. comment créez-vous cette première instance? –

Répondre

147

Vous devez changer la ligne this.MyDateTime = myNewDT.MyDateTime.Value; juste this.MyDateTime = myNewDT.MyDateTime;

L'exception que vous recevez a été jeté dans la .Value propriété du NullableDateTime, comme est nécessaire pour retourner un DateTime (puisque c'est ce que le contrat pour .Value états), mais il ne peut pas le faire parce qu'il n'y a pas DateTime à retourner, donc il jette une exception.

En général, il est une mauvaise idée d'appeler aveuglément .Value sur un type Nullable, à moins que vous avez une certaine connaissance préalable que cette variable MUST contiennent une valeur (à savoir par un chèque .HasValue).

EDIT

Voici le code pour DateTimeExtended qui ne jette pas une exception:

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

    public DateTimeExtended() { } 

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

Je l'ai testé comme ceci:

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

Ajout du .Value sur other.MyDateTime provoque une exception. Le supprimer supprime l'exception. Je pense que vous cherchez au mauvais endroit.

+0

Vous avez raison sur le .value, mais quelque chose d'autre provoque l'exception. J'ai supprimé le .value, et j'ai changé l'ordre de code de la constructeur - en copiant la valeur int en premier, mais la même exception est levée. – Dani

+0

J'ai commenté la question - trouvé le problème, il était dans un setter généré pour les propriétés. – Dani

+0

oui, son résolu mon problème, je viens de changer l'objet null null à non null capable, et convertir datetime en chaîne directement, pas par datetimeobject.value.datetime.tostring() – adnan

4

Essayez laissant tomber le .value

+0

n'aide pas. il lance la même exception si je cours la première ligne en premier. – Dani

1

affecter les membres directement sans .Value partie:

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

Dans ce cas oldDTE est nulle, donc quand vous essayez d'accéder à la oldDTE.Value InvalidOperationException est levée depuis il n'y a pas de valeur. Dans votre exemple, vous pouvez simplement faire:

this.MyDateTime = newDT.MyDateTime; 
+0

L'ancienDTE n'est pas nul, mais j'ai supprimé la valeur de toute façon ... il lance toujours cette exception .... – Dani

0

On dirait que oldDTE.MyDateTime était nul, donc constructeur a essayé de prendre sa valeur - qui a jeté.

0

J'ai reçu ce message lorsque j'essayais d'accéder aux valeurs d'un objet à valeur nulle.

sName = myObj.Name; 

cela produira une erreur. D'abord vous devriez vérifier si l'objet n'est pas nul

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

Cela fonctionne.

+0

Avant de répondre, s'il vous plaît essayer de lire d'abord les autres réponses à la question - en particulier la réponse acceptée qui indique exactement ce que vous avez placé dans * votre * réponse. Bien qu'il ne le montre pas en utilisant du code, il l'énonce. Aussi, essayez de rendre votre exemple de code pertinent à la question - comme 'this.MyDateTime = myNewDT.MyDateTime.Value;', pas 'sName = myObj.Name;' – newfurniturey

2

Lors de l'utilisation des méthodes d'extension LINQ (par exemple Select, Where), la fonction lambda peut être converti en SQL qui pourraient ne pas comporter de manière identique à votre code C#. Par exemple, le court-circuit de C# évalué || et && sont convertis en AND et OR. Cela peut causer des problèmes lorsque vous vérifiez null dans votre lambda.

Exemple:

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

Je réalise que cette réponse n'est pas pertinente pour le cas spécifique de l'OP , mais c'est pertinent à l'exception qu'il obtient. En outre, cette page est le premier hit sur Google pour cette exception, ce qui le rend pertinent. –

Questions connexes