web-dev-qa-db-ja.com

ヌル可能オブジェクトには値が必要です

例外の説明にはパラドックスがあります。Nullableオブジェクトには値(?!)が必要です

これが問題です:

DateTimeExtendedクラスがあります。

{
  DateTime? MyDataTime;
  int? otherdata;

}

およびコンストラクター

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

このコードを実行する

DateTimeExtended res = new DateTimeExtended(oldDTE);

メッセージとともにInvalidOperationExceptionをスローします。

Nullableオブジェクトには値が必要です。

myNewDT.MyDateTime.Value-有効であり、通常のDateTimeオブジェクトが含まれています。

このメッセージの意味は何ですか?また、私は何を間違っていますか?

oldDTEnullではないことに注意してください。 myNewDT.MyDateTimeからValueを削除しましたが、セッターが生成されたために同じ例外がスローされます。

158
Dani

this.MyDateTime = myNewDT.MyDateTime.Value;を単にthis.MyDateTime = myNewDT.MyDateTime;に変更する必要があります

あなたが受け取っていた例外は.ValueNullableDateTimeのプロパティでスローされました。DateTimeを返す必要があるためです.Valueのコントラクト)ですが、返されるDateTimeがないため、返せないため、例外がスローされます。

一般に、その変数MUSTに値が含まれているという事前知識がない限り(つまり.Valueを介して)、null許容型で盲目的に.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);

.Valueother.MyDateTimeを追加すると、例外が発生します。それを削除すると、例外は取り除かれます。間違った場所を見ていると思います。

175
Yuliy

LINQ拡張メソッド(SelectWhereなど)を使用する場合、ラムダ関数はSQLに変換され、C#コードとまったく同じように動作しない場合があります。たとえば、C#の短絡評価||および&&は、SQLの熱心なANDおよびORに変換されます。これは、ラムダでnullをチェックしているときに問題を引き起こす可能性があります。

例:

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

.valueをドロップしてみてください

5
Paul Creasey

この場合、oldDTEはnullであるため、oldDTE.Valueにアクセスしようとすると、値がないためInvalidOperationExceptionがスローされます。あなたの例では、単に次のことができます:

this.MyDateTime = newDT.MyDateTime;
2
Lee

.Value部分なしでメンバーを直接割り当てます。

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

OldDTE.MyDateTimeがnullのように見えるため、コンストラクタはValueを取得しようとしましたが、これがスローされました。

0

Null値のオブジェクトの値にアクセスしようとしたときにこのメッセージが表示されました。

sName = myObj.Name;

これによりエラーが発生します。最初に、オブジェクトがnullでないかどうかを確認する必要があります

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

これは動作します。

0
Juris