null olabilecek nesnenin bir değeri olmalıdır


190

Kural dışı durum açıklamasında paradoks var: Null olabilecek nesnenin bir değeri olmalıdır (?!)

Sorun bu:

Bir DateTimeExtendeddersim var,

{
  DateTime? MyDataTime;
  int? otherdata;

}

ve bir kurucu

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

bu kodu çalıştırmak

DateTimeExtended res = new DateTimeExtended(oldDTE);

InvalidOperationExceptionmesajı ile bir atar :

Null olabilecek nesnenin bir değeri olmalıdır.

myNewDT.MyDateTime.Value- geçerlidir ve normal bir DateTimenesne içerir.

Bu mesajın anlamı nedir ve neyi yanlış yapıyorum?

Not oldDTEdeğildir null. Ben kaldırdık Valuegelen myNewDT.MyDateTimeama aynı istisnası oluşturulan setter nedeniyle atılır.


Diğer kurucu nedir?
Paul Creasey

Garip. Buradaki .Value ile istisnayı yeniden oluşturuyorum ve .Value olmadan istisna alamıyorum. Güncellenmiş kodu çalıştırdığınızdan emin misiniz?
Yuliy

Yapıcı kendisinin bir örneğini alır. bu ilk örneği nasıl oluşturuyorsun?
Paul Creasey

parametreler olmadan new () olarak oluşturulur ve sonra değerleri eklerim (çalışır).
Dani

6
Sorun çözüldü - sorun yoktu ... otherdata ve MyDateTime için oluşturulan bir ayarlayıcı vardı, bu ayarlamadan önce değeri kontrol ediyordu .. boş olduğunda uçan !!!
Dani

Yanıtlar:


201

Çizgiyi this.MyDateTime = myNewDT.MyDateTime.Value;sadecethis.MyDateTime = myNewDT.MyDateTime;

Aldığınız istisna, .Value Nullable'ın mülküneDateTime , çünkü bir geri dönmek gerekiyor DateTime(çünkü .Valuedevletler için sözleşme budur ), ancak bunu yapamaz çünkü DateTimegeri dönüş yok , bu yüzden bir istisna atar.

Genel olarak, bu .Valuedeğişkenin bir değer içermesi GEREKİR (yani bir .HasValuekontrol yoluyla ) hakkında önceden bir bilginiz yoksa, nullable tipini körü körüne çağırmak kötü bir fikirdir .

DÜZENLE

İşte DateTimeExtendedbir istisna atmaz kod :

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

    public DateTimeExtended() { }

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

Ben böyle test:

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

.ValueTarihinde eklenmesi other.MyDateTimebir istisnaya neden olur. Kaldırmak istisnadan kurtulur. Bence yanlış yere bakıyorsun.


.Value hakkinda haklisiniz, ancak baska bir sey istisnaya neden oluyor. .Value kaldırdım ve ilk int değerini kopyalayarak yapıcı kod sırasını değiştirdim, ama aynı istisna atılır.
Dani

Soruyu yorumladım - sorunu buldum, özellikler için oluşturulan bir ayarlayıcıydı.
Dani

evet, bu benim sorunum çözüldü, ben sadece boş null mümkün olmayan null mümkün nesne değiştirmek ve datetime doğrudan datetimeobject.value.datetime.tostring ()
adnan

Mükemmel cevap. .ValueBoş bir nesneye çağrı yapan bir istisna almak mantıklıdır (sanırım), ancak iki Nullable nesnesiyle uğraşıyorsanız istisna mesajı gerçekten yanıltıcıdır. '.Value özelliği nesnenin boş olmamasını gerektirir' gibi bir şey çok daha mantıklı olacaktır.
DVK

9

LINQ genişletme yöntemlerini (örn Select. Where) Kullanırken , lambda işlevi C # kodunuzla aynı şekilde davranmayabilecek SQL'e dönüştürülebilir. Örneğin, C # 'ın kısa devresi değerlendirilir &&ve ||SQL'in istekli ANDve dönüştürülür OR. Bu, lambda'nızda null olup olmadığını kontrol ederken sorunlara neden olabilir.

Misal:

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

5
Bu cevabın OP'nin özel durumu ile ilgili olmadığını, ancak aldığı İstisna ile ilgili olduğunu anlıyorum. Ayrıca, bu sayfa söz konusu istisna için Google'daki ilk isabettir.
Koruyucu bir

6

Bırakmayı deneyin .value

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

yardımcı olmuyor. önce 2. satırı çalıştırırsam aynı istisnayı atar.
Dani

2

Bu durumda oldDTE null olur, bu nedenle oldDTE.Value öğesine erişmeye çalıştığınızda değer olmadığından InvalidOperationException oluşturulur. Örneğinizde şunları yapabilirsiniz:

this.MyDateTime = newDT.MyDateTime;

OldDTE null değil, ama yine de değeri kaldırdım ... hala bu istisnayı atıyor ....
Dani

1

Üyeleri doğrudan .Valueparça olmadan atayın :

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

0

OldDTE.MyDateTime null gibi görünüyor, bu yüzden yapıcı Değer'i almaya çalıştı - ki attı.


0

Boş değerli bir nesnenin değerlerine erişmeye çalışırken bu iletiyi aldım.

sName = myObj.Name;

bu hataya neden olur. Önce nesnenin boş olup olmadığını kontrol etmelisiniz

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

Bu çalışıyor.


1
Yanıtlama önce, ilk soru için diğer yanıtlar okumaya deneyin - devletler sen yerleştirilir tam olarak ne olduğunu, özellikle kabul cevabı sizin cevap. Kod kullanarak göstermese de, heceleyerek açıklar. Ayrıca, örnek kodunuzu soruyla alakalı hale getirmeye çalışın - örneğin this.MyDateTime = myNewDT.MyDateTime.Value;, değilsName = myObj.Name;
newfurniturey

0

Bu çözümü aldım ve benim için çalışıyor

if (myNewDT.MyDateTime == null)
{
   myNewDT.MyDateTime = DateTime.Now();
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.