web-dev-qa-db-fra.com

l'objet nullable doit avoir une valeur

Il y a un paradoxe dans la description de l'exception: l'objet Nullable doit avoir une valeur (?!)

C'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:

L'objet nullable doit avoir une valeur.

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

Quel est le sens de ce message et que fais-je de travers?

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

167
Dani

Vous devez modifier la ligne _this.MyDateTime = myNewDT.MyDateTime.Value;_ en _this.MyDateTime = myNewDT.MyDateTime;_

L'exception que vous receviez a été levée dans la propriété .Value de NullableDateTime, car il est nécessaire de renvoyer un DateTime (puisque c'est ce que stipule le contrat pour _.Value_), mais il ne peut pas le faire car il n'y a pas de variable DateTime à renvoyer, elle génère donc une exception.

En général, c’est une mauvaise idée d’appeler aveuglément _.Value_ sur un type nullable, sauf si vous savez au préalable que cette variable DOIT contient une valeur (c'est-à-dire par le biais d'un .HasValue cocher).

EDIT

Voici le code pour DateTimeExtended qui ne lève pas d'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 ça:

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

L'ajout de _.Value_ sur _other.MyDateTime_ provoque une exception. Le supprimer supprime l'exception. Je pense que vous cherchez au mauvais endroit.

175
Yuliy

Lorsque vous utilisez des méthodes d'extension LINQ (par exemple, Select, Where), la fonction lambda peut être convertie en SQL sans que son comportement ne soit pas identique à celui de votre code C #. Par exemple, le court-circuit évalué par C # || et && est converti en SQL désireux AND et OR. Cela peut entraîner des problèmes lorsque vous recherchez la valeur 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
8
Protector one

Essayez de laisser tomber le .value

_DateTimeExtended(DateTimeExtended myNewDT)
{
   this.MyDateTime = myNewDT.MyDateTime;
   this.otherdata = myNewDT.otherdata;
}
_
5
Paul Creasey

Dans ce cas oldDTE a la valeur null. Ainsi, lorsque vous essayez d'accéder à oldDTE.Value, l'exception InvalidOperationException est levée car il n'y a pas de valeur. Dans votre exemple, vous pouvez simplement faire:

this.MyDateTime = newDT.MyDateTime;
2
Lee

Affectez les membres directement sans la partie .Value:

DateTimeExtended(DateTimeExtended myNewDT)
{
   this.MyDateTime = myNewDT.MyDateTime;
   this.otherdata = myNewDT.otherdata;
}
1
Cecil Has a Name

On dirait que oldDTE.MyDateTime était null, le constructeur a donc essayé de prendre sa valeur - qui l'a renvoyée.

0
Pavel Radzivilovsky

J'ai reçu ce message en essayant 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 null

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

Cela marche.

0
Juris