null許容オブジェクトには値が必要です


189

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

これが問題です:

私はDateTimeExtendedクラスを持っています

{
  DateTime? MyDataTime;
  int? otherdata;

}

そしてコンストラクタ

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

このコードを実行する

DateTimeExtended res = new DateTimeExtended(oldDTE);

InvalidOperationExceptionメッセージをスローします:

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

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

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

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


他のコンストラクタは何ですか?
Paul Creasey、

奇妙な。そこに.Valueがある例外を再現しますが、そこに.Valueがないと例外は発生しません。更新されたコードを実行していますか?
Yuliy、

コンストラクターはそれ自体のインスタンスを取得します。最初のインスタンスをどのように作成していますか?
Paul Creasey、

パラメータなしでnew()として構築され、値を追加します(機能します)。
ダニ

6
問題は解決しました-問題はありませんでした... otherdataとMyDateTimeへの生成されたセッターがあり、値を設定する前に値をチェックしていました。nullのときに飛んでいました!!!
ダニ

回答:


201

this.MyDateTime = myNewDT.MyDateTime.Value;をちょうどに変更する必要がありますthis.MyDateTime = myNewDT.MyDateTime;

受け取った例外.Valueは、nullable のプロパティでスローされました。DateTimeこれは、DateTime(それが.Value状態のコントラクトであるため)を返す必要があるためですが、返す必要がないためにそうすることができないためDateTime、例外がスローされます。

一般に、.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);

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


あなたは.valueについて正しいですが、何か他のものが例外を引き起こします。.valueを削除し、コンストラクターのコード順序を変更しました。最初にint値をコピーしましたが、同じ例外がスローされます。
ダニ、

私は質問にコメントしました-問題を見つけました、それはプロパティの生成されたセッターにありました。
ダニ

はい、問題は解決しました。null対応オブジェクトをnull非対応オブジェクトに変更し、datetimeobject.value.datetime.tostring()ではなく、datetimeを文字列に直接変換します
adnan

すばらしい答えです。.Valuenullオブジェクトで例外呼び出しを取得することは理にかなっています(私は推測します)が、2つのNullableオブジェクトを処理している場合、例外メッセージは本当に誤解を招くものです。「.Valueプロパティはオブジェクトがnull以外である必要がある」のようなものは、もっとずっと理にかなっています。
DVK 2017

9

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

例:

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

5
この答えはOPの特定のケースとは関係ありませんが、彼が得る例外と関係があることに気づきました。また、このページはその例外に対するGoogleの最初のヒットであり、関連性があります。
プロテクター1

6

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

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

助けにはならない。最初に2行目を実行すると、同じ例外がスローされます。
ダニ、

2

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

this.MyDateTime = newDT.MyDateTime;

oldDTEはnullではありませんが、とにかく値を削除しました...それでも例外がスローされます...
Dani

1

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

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


0

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

sName = myObj.Name;

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

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

これは機能します。


1
回答する前に、質問に対する他の回答を最初に読んでみてください。特に、あなたが回答に何を入れたかを正確に述べた、受け入れられた回答です。それはコードを使用してそれを示しませんが、それはそれを綴ります。など-また、質問者へのあなたのサンプルコードは、関連するようにしようthis.MyDateTime = myNewDT.MyDateTime.Value;ではない、sName = myObj.Name;
newfurniturey
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.