null
Değeri ve is
İşleci
Önceki bölümlerde gördüğümüz gibi, referans türünden olan değişkenler hiçbir nesneye erişim sağlamadan da oluşturulabilirler:
BirSınıf erişimSağlayan = new BirSınıf; BirSınıf değişken; // erişim sağlamayan
Bir referans türü olduğu için yukarıdaki değişken
'in bir kimliği vardır; ama erişim sağladığı bir nesne henüz yoktur. Böyle bir değişkenin bellekte şu şekilde durduğunu düşünebiliriz:
değişken ───┬──────┬─── │ null │ ───┴──────┴───
Hiçbir nesneye erişim sağlamayan referansların değerleri null
'dır. Bunu aşağıda anlatıyorum.
Böyle bir değişken kendisine bir nesne atanana kadar kullanılamaz bir durumdadır. Doğal olarak, erişim sağladığı bir BirSınıf
nesnesi olmadığı için o değişken ile işlemler yapmamız beklenemez:
import std.stdio; class BirSınıf { int üye; } void kullan(BirSınıf değişken) { writeln(değişken.üye); // ← HATA } void main() { BirSınıf değişken; kullan(değişken); }
kullan
işlevine verilen değişken hiçbir nesneye erişim sağlamadığından, olmayan nesnenin üye
'sine erişilmeye çalışılması programın çökmesine neden olur:
$ ./deneme
Segmentation fault
"Segmentation fault", programın geçerli olmayan bir bellek bölgesine erişmeye çalıştığı için işletim sistemi tarafından acil olarak sonlandırıldığını gösterir.
null
değeri
Erişim sağladığı nesne henüz belli olmayan referans türü değişkenleri null
özel değerine sahiptir. Bu değeri de herhangi başka bir değer gibi yazdırabiliriz:
writeln(null);
Çıktısı:
null
Değeri null
olan bir değişken çok kısıtlı sayıda işlemde kullanılabilir:
- Erişim sağlaması için geçerli bir nesne atamak
değişken = new BirSınıf; // artık nesnesi var
O atamadan sonra artık
değişken
'in erişim sağladığı bir nesne vardır.değişken
artıkBirSınıf
işlemleri için kullanılabilir. null
olup olmadığını denetlemekif (değişken == null) // ← derleme HATASI
Ne yazık ki,
==
işleci asıl nesneleri karşılaştırdığı için; venull
bir değişkenin eriştirdiği geçerli bir nesne olmadığı için, o ifade derlenemez.Bu yüzden, bir değişkenin
null
olup olmadığını denetlemek içinis
işleci kullanılır.
is
işleci
is
, İngilizce'de "olmak" fiilinin "öyledir" kullanımındaki anlamına sahiptir. Bu bölümü ilgilendiren kullanımında ikili bir işleçtir, yani sol ve sağ tarafına iki değer alır. Bu iki değer aynıysa true
, değilse false
üretir.
Not: is
'in örneğin şablon olanağında tekli işleç olarak kullanıldığı durumlar da vardır.
İki değerden birisinin null
olabildiği durumlarda ==
işlecinin kullanılamadığını yukarıda gördük. Onun yerine is
'i kullanmak gerekir. "Bu değişken null ise" koşulunu denetlemeye yarar:
if (değişken is null) { // hiçbir nesneye erişim sağlamıyor }
is
, başka türlerle de kullanılabilir. Örneğin iki tamsayı değişkenin değerleri şöyle karşılaştırılabilir:
if (hız is yeniHız) { // ikisi aynı değerde } else { // ikisi farklı değerde }
Dilimlerde de iki dilimin aynı elemanlara erişim sağlayıp sağlamadıklarını denetler:
if (dilim is dilim2) { // aynı elemanları paylaşıyorlar }
!is
işleci
==
ve !=
işleçlerine benzer şekilde, is
'in tersi !is
işlecidir. Değerler eşit olmadığında true
üretir:
if (hız !is yeniHız) { // farklı değerlere sahipler }
null
değer atamak
Referans türünden olan bir değişkene null
değerini atamak, o değişkenin artık hiçbir nesneye erişim sağlamamasına neden olur.
Eğer bu atama sonucunda asıl nesneye erişen başka referans değişkeni kalmamışsa, asıl nesne çöp toplayıcı tarafından sonlandırılacaktır. Hiçbir referans tarafından erişilmiyor olması, o nesnenin artık kullanılmadığını gösterir.
Örnek olarak, önceki bir bölümde gördüğümüz iki değişkenin aynı nesneye eriştikleri duruma bakalım:
auto değişken = new BirSınıf; auto değişken2 = değişken;
(isimsiz BirSınıf nesnesi) değişken değişken2 ───┬───────────────────┬─── ───┬───┬─── ───┬───┬─── │ ... │ │ o │ │ o │ ───┴───────────────────┴─── ───┴─│─┴─── ───┴─│─┴─── ▲ │ │ │ │ │ └────────────────────┴────────────┘
Bu değişkenlerden birisine null
atamak, onun bu değerle ilişkisini keser:
değişken = null;
BirSınıf
nesnesine artık yalnızca değişken2
tarafından erişilmektedir:
(isimsiz BirSınıf nesnesi) değişken değişken2 ───┬───────────────────┬─── ───┬────┬─── ───┬───┬─── │ ... │ │null│ │ o │ ───┴───────────────────┴─── ───┴────┴─── ───┴─│─┴─── ▲ │ │ │ └──────────────────────────────────┘
İsimsiz BirSınıf
nesnesine erişen son referans olan değişken2
'ye de null
atanması, asıl nesnenin sonlanmasına neden olur:
değişken2 = null;
Çöp toplayıcı asıl nesneyi türüne göre ya hemen, ya da ilerideki bir zamanda sonlandıracaktır. Program açısından artık o nesne yoktur çünkü o nesneye erişen referans kalmamıştır:
değişken değişken2 ───┬───────────────────┬─── ───┬────┬─── ───┬────┬─── │ │ │null│ │null│ ───┴───────────────────┴─── ───┴────┴─── ───┴────┴──
Eşleme tabloları bölümünün birinci problemi, bir eşleme tablosunu boşaltan üç yöntem gösteriyordu. Şimdi o yöntemlere bir dördüncüsünü ekleyebiliriz; eşleme tablosu değişkenine null
değer atamak, değişkenin erişim sağladığı asıl tablo ile ilişkisini keser:
string[int] isimleSayılar; // ... isimleSayılar = null; // artık hiçbir elemana erişim // sağlamaz
Yukarıdaki BirSınıf
örneğine benzer şekilde, eğer isimleSayılar
asıl tabloya erişim sağlayan son referans idiyse, asıl tablonun elemanları çöp toplayıcı tarafından sonlandırılacaklardır.
Bir dilimin de artık hiçbir elemana erişim sağlaması istenmiyorsa null
atanabilir:
int[] dilim = dizi[ 10 .. 20 ]; // ... dilim = null; // artık hiçbir elemana erişim sağlamaz
Özet
null
, hiçbir değere erişim sağlamayan referans değeridirnull
referanslar yalnızca iki işlemde kullanılabilirler: değer atamak,null
olup olmadığını denetlemek==
işleci asıl nesneye erişmeyi gerektirebileceği için,null
olma olasılığı bulunan referanslaris
ile denetlenmelidiris
'in tersi!is
'dirnull
atanan referans artık hiçbir elemana erişim sağlamaz- Hiçbir referansın erişim sağlamadığı nesneler çöp toplayıcı tarafından sonlandırılırlar