Genel

NullReferenceException Hatası ve Çözümü

C#, Java gibi Nesne Yönelimli Programlama Dillerinde nesneler ve değişkenler bellek yönetimi açısından farklı davranış sergilerler. Kullanımları her ne kadar basit olarak görsekte uygulama testlerinde aldığımız C# dahilinde “NullReferenceException”, veya Java dahilinde “NullPointerException” türevinden hatalar en sık karşılaştıklarımız arasındadır. “NullReferenceException” hatası çözümü, uygulama nesnelerinin bellek yönetimi açısından düşünülerek cevaplanması gereken bir yöntemdir. Peki nedir bu “Null” olma durumu ve “NullReferenceException” hatasını neden alırız.

Bu soruyu yanıtlamadan önce C# Değer ve Referans Tipi Bellek Yönetimi yazısını okumanızı öneririm.

Bir sınıf türü değişkeni “new” anahtar kelimesi ile örneklemediğinizde nesne “null” durumda bulunacaktır.

Nesnenin kullanılabilmesi için mutlaka “new” anahtar kelimesi ile örneklendirilmiş olması gerekmektedir.

Null durumda bırakılmış bir nesneyi kulanmaya çalışmak demek “NullRefrenceException” hatasını alacağınız anlamına gelmektedir. Daha iyi anlamak için basit bir örnekle inceleyelim;

Yukarıdaki senaryo incelendiğinde k1 nesnesinin Kitap tipinde tanımlandığı ancak new anahtar kelimesi ile örneklenmediği görülmektedir. Bu bir sorun değil. Böyle bir durumda k1 nesnesi null değerine sahip olacaktır. Ancak sonraki adımda k1 nesnesinin “Baslik” isimli özelliğine erişim yapılmıştır ki işte bu nota “NullRefrenceException” hatasını beraberinde fırlatacaktır.

Şimdi bu hatayı alabileceğimiz farklı uygulama senaryolarına bir gözatalım;

  • Bir nesneye bilinçli olarak null değer atama;
    “Null” değer atanmış nesnelerin üye elemanlarına çalışma zamanında ulaşmak istenmesi halinde “NullReferenceException” hatası alınır. Ancak bazı derleyiciler, “Use of unassigned local variable names” hatasını önceden fırlatabilirler. Bu hata ilk değer atamasının yapılmadığı anlamına gelir.
  • “new” anahtar kelimesi kullanmadan nesne’yi kullanmaya çalışmak;
    Bir başvuru (sınıf) türü bir değişken oluştururken, varsayılan olarak “null” değeri atanmış olur. Sınıf türü değişkenler başlatılmalı veya varolan sınıf örneğine ayarlanmalıdır. Başlatma, “new” anahtar kelime kullanılarak yapılır .
  • İç içe geçmiş sınıflarda yapıcı metodlarda (constructor) uygun başlatımların yapılmaması;
    Uygulama testinde alınan sonuç;

    Uygulama tarafında (Main Metodu)  Kitap sınıfı “new” anahtar kelimesi ile örneklenmiş ve üyesi olan Yazar nesnesine erişim yapılmıştır. Ancak Yazar nesnesi için herhangi bir başlatıcı (constructor) bulunmamaktadır. Yazar özelliği Kisi sınıf tipinde olup kendi uyesi Yas özelliğine başvuru yapılması sonucu “NullReferenceException” hatasını fırlatacaktır.
    Sorunun çözümü için Kitap sınıfında bir başlatıcı metod yazımı uygun olacaktır.

     

  • Sınıf değişkenlerinin kapsam alanlarında örneklenmemiş olmaları;

    Form1_Load()” metodu altında musteri nesnesi örneklenmiş gibi görünsede “Button_Click()” metodu altında Ad özelliğine başvurusu yapılan musteri sınıf değişkeni global alanda tanımlanmış olana işaret eder. Global alanda tanımlanmış musteri değişkeni null durumdadır.

  •  ASP.NET sayfalarının yaşam döngülerinden kaynaklanabilir.

    Yukarıdaki ASP.NET WebForm örnek uygulamasında sayfanın ilk yüklemesinden (Page_Load())  doğan IsPostBack kontrolü ile myTest sınıf değişkeni örneklemesi yapılmaktadır. Ancak aynı oturum sayfası yenilendiğinde (refresh) if bloğuna giremeyecek ve değişken örneklemesi ikinci kez yapılamayacaktır. ASP.NET yaşam döngüsünden kaynaklı olarak ikinci kez oluşturulan sınıf değişkeni “null” durumunda kalacaktır. Görüldüğü üzere SaveButton_click() metodunda bu nesnenin .deger üyesine başvuru yapılmıştır. Sonuçta ilk uygulama çalıştığı anda herşey normal ilerlerken sayfa yenilenir ve SaveButton_Click() yöntemi çağırılırsa uygulama “NullReferenceException” hatasını fırlatacaktır. Bu gibi bir senaryoda Session nesnelerini kullanmanız hata deneti

  • WPF kontrollerinin oluşturma sıralamasından kaynaklı hatalar;
    WPF denetimleri XAML ile deklare edilen sıralamada kontroller hafızadaki yerlerini alırlar. Bir kontrol yüklenmeden işletmeye alınması “NullReferenceException” hatasını fırlatacaktır. Örneğin;

    Combobox ilk sırada Label kontrolünden önce oluşturulmuştur. Ancak Combobox’ın SelectionChanged olayı ile Label kontrolüne başvuru programatik yönden yapılmıştır. Yükleme esnasında Combobox kontrolü öğelerini oluştururken bu olayı tetikleyecektir. Bu esnada Label kontrolü daha oluşturulmamıştır. Bu noktada “NullReferenceException” hatasını fırlatır.

    Çözümü ise basit olarak tasarım kaygılarını görmezden gelip XAML tarafında Label kontrolünü Combobox’tan önce bildirimi yapılmış olmalıdır.

  • LINQ Deyimlerinde Single(), First() metodlarında dönen değer olmadığında null durumda kalırlar. Bunun yerine OrDefault sürümlerini kullanın. Single() yerine SingleOrDefault(), First() yerine FirstOrDefault() tercih edilmelidir.

NullReferenceException Hatasının Olası Çözümleri

  • Nesnenin bazen null değere sahip olabileceği potansiyelini görebilirsiniz. Nesnenin üyelerine erişmeden öncenull” değer taşıyor mu diye kontrol edin;
  • Yazdığınız metodlarınız da geri dönüş değerinin null olabilme ihtimali doğabilir. Örneğin aranan değer bulunamadığında geriye null yerine varsayılan bir değer döndürmeyi tercih ediniz.
  • Dinamik yolla oluşturduğunuz (var) değişkenlerinizi açıkça kontrol ediniz. Hata olma ihtimallerine karşı, kontrollü özel istisnaları fırlatabilirsiniz.
  • Null değer döndürebilme ihtimali olan düz kullanımlı metodları çağırmak yerine onların OrDefault  sürümlerini kullanmaya çalışın. Örneğin tarihsel (DateTime) türünde değişkenden değer okumak için kullanılan “GetValue()” yerine “GetValueOrDefault()” yöntemini kullanmak daha uygun bir çözüm olacaktır.
  • Ternary operatörleri ile null değer kontrolü yapınız. Eğer null değer taşıyacaksa, varsayılan değerler atayın. Aşağıdaki örnekleri inceleyiniz.
     

About the author

admin

Add Comment

Click here to post a comment

Bu site, istenmeyenleri azaltmak için Akismet kullanıyor. Yorum verilerinizin nasıl işlendiği hakkında daha fazla bilgi edinin.