Objecto nulo deve ter um valor

189

Existe um paradoxo na descrição da exceção: o objeto nulo deve ter um valor (?!)

Este é o problema:

Eu tenho uma DateTimeExtendedaula que tem

{
  DateTime? MyDataTime;
  int? otherdata;

}

e um construtor

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

executando este código

DateTimeExtended res = new DateTimeExtended(oldDTE);

lança um InvalidOperationExceptioncom a mensagem:

Objecto nulo deve ter um valor.

myNewDT.MyDateTime.Value- é válido e contém um DateTimeobjeto regular .

Qual é o significado desta mensagem e o que estou fazendo de errado?

Note que oldDTEnão é null. Eu removi o Valuede myNewDT.MyDateTimemas a mesma exceção é lançada devido a um setter gerado.

Dani
fonte
Qual é o outro construtor?
Paul Creasey
Estranho. Eu reproduzo a exceção com o .Value lá e não recebo nenhuma exceção sem o .Value lá. Tem certeza de que está executando o código atualizado?
309 Yuliy
O construtor toma uma instância de si mesmo. como você está criando essa primeira instância?
Paul Creasey
é construído como new () sem parâmetros e, em seguida, adiciono os valores (funciona).
13449 Dani
6
Problema resolvido - o problema não estava lá ... havia um setter gerado para os outros dados e MyDateTime, que estavam verificando o valor antes de configurá-lo .. voando quando é nulo !!!
1374 Dani

Respostas:

201

Você deve alterar a linha this.MyDateTime = myNewDT.MyDateTime.Value;para apenasthis.MyDateTime = myNewDT.MyDateTime;

A exceção que você estava recebendo foi lançada na .Valuepropriedade Nullable DateTime , pois é necessário devolver um DateTime(já que esse é o contrato para os .Valueestados), mas não pode fazê-lo porque não há DateTimeretorno, então lança uma exceção.

Em geral, é uma má idéia chamar cegamente .Valueum tipo anulável, a menos que você tenha algum conhecimento prévio de que essa variável DEVE conter um valor (por exemplo, através de uma .HasValueverificação).

EDITAR

Aqui está o código para DateTimeExtendedisso não gera uma exceção:

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

    public DateTimeExtended() { }

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

Eu testei assim:

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

Adicionar o .Valueon other.MyDateTimecausa uma exceção. Removê-lo se livra da exceção. Eu acho que você está procurando no lugar errado.

Yuliy
fonte
Você está certo sobre o valor. Ainda outra coisa causa a exceção. Eu removi o .value e alterei a ordem do código do construtor, copiando o valor int primeiro, mas a mesma exceção é lançada.
1313 Dani
Eu comentei a questão - encontrei o problema, estava em um setter gerado para as propriedades.
13769 Dani
sim, sua resolvido o meu problema, eu apenas mudar nulo objeto capaz de nulo capaz non, e converter datetime para string diretamente, e não por datetimeobject.value.datetime.tostring ()
adnan
Ótima resposta. Obter uma exceção chamando .Valueum objeto nulo faz sentido (eu acho), mas a mensagem de exceção é realmente enganosa se você estiver lidando com dois objetos Nullable. Algo como 'A propriedade .Value exige que o objeto seja não nulo' faria muito mais sentido.
DVK
9

Ao usar métodos de extensão LINQ (por exemplo Select, Where), a função lambda pode ser convertida em SQL que pode não se comportar de forma idêntica ao seu código C #. Por exemplo, o curto-circuito do C # é avaliado &&e ||convertido em ansioso ANDe OR. Isso pode causar problemas quando você está checando nulo em sua lambda.

Exemplo:

MyEnum? type = null;
Entities.Table.Where(a => type == null || 
    a.type == (int)type).ToArray();  // Exception: Nullable object must have a value
Protetor um
fonte
5
Sei que essa resposta não é relevante para o caso específico do OP, mas é relevante para a exceção que ele está recebendo. Além disso, esta página é o primeiro hit no Google para essa exceção, o que a torna relevante.
Protector one
6

Tente soltar o .value

DateTimeExtended(DateTimeExtended myNewDT)
{
   this.MyDateTime = myNewDT.MyDateTime;
   this.otherdata = myNewDT.otherdata;
}
Paul Creasey
fonte
não ajuda. ele lança a mesma exceção se eu executar a segunda linha primeiro.
13769 Dani
2

Nesse caso, oldDTE é nulo; portanto, quando você tenta acessar oldDTE.Value, InvalidOperationException é lançada, pois não há valor. No seu exemplo, você pode simplesmente fazer:

this.MyDateTime = newDT.MyDateTime;
Lee
fonte
O oldDTE não é nulo, mas eu removi o valor de qualquer maneira ... ele ainda está jogando essa exceção ....
Dani
1

Atribua os membros diretamente sem a .Valueparte:

DateTimeExtended(DateTimeExtended myNewDT)
{
   this.MyDateTime = myNewDT.MyDateTime;
   this.otherdata = myNewDT.otherdata;
}
Cecil tem um nome
fonte
0

Parece que oldDTE.MyDateTime era nulo, então o construtor tentou usar o Value - que foi lançado.

Pavel Radzivilovsky
fonte
0

Recebi esta mensagem ao tentar acessar valores de um objeto com valor nulo.

sName = myObj.Name;

isso produzirá erro. Primeiro você deve verificar se o objeto não é nulo

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

Isso funciona.

Juris
fonte
1
Antes de responder, tente ler as outras respostas primeiro, especialmente a resposta aceita, que indica exatamente o que você colocou na sua resposta. Embora não o exiba usando código, ele é explicitado. Além disso, tente fazer o seu código de exemplo relevante para a questão de - como this.MyDateTime = myNewDT.MyDateTime.Value;, nãosName = myObj.Name;
newfurniturey