Bilindiği gibi değişken tipleri, depolanma durumları ve davranışları bakımından değer ve referans olmak üzere ikiye ayrılır. Bu iki veri tipi arasındaki önemli bir farktan bahsedeceğiz; referans türlerinin null(nothing) değeri alabiliyorken değer türlerinin bu özelliği taşımıyor olmasıdır. Yani değer türleri, her zaman bir değer taşımak zorundadır. Bir değişkenin, null olması, herhangi bir nesneye işaret etmiyor olduğu anlamına gelir. Özellikle veritabanı işlemlerinde null tabanlı kolonlarla çalışıldığında veya uygulama içerisinde değişkenlerin herhangi bir değer taşımaması gereken durumlarda bu özellik önem kazanmaktadır. Örneğin boolean türünde bir değişkenin değerini veritabanına göndereceğimizi düşünelim. Kullanıcı bu değeri, ya false ya da true olarak set edecektir. Peki, kullanıcının bu değeri set etmeden önce bu değişkenin default değeri ne olacak veya kullanıcı hiçbir şekilde bu değişkenin değerini set etmediyse veritabanına hangi değer gönderilecek.
Dim Sonuc1 As Boolean Dim Sonuc2 As Boolean = Nothing Console.WriteLine(Sonuc1) 'False Console.WriteLine(Sonuc2) 'False
VB.NET tarafında görüldüğü gibi Sonuc2 değişkeni Nothing olarak set edildiği halde false değerini taşımaktadır. C# tarafında bu şekilde bir tanımlama hataya neden olacaktır.
bool Sonuc1; //Use of unassigned local variable 'Sonuc' bool Sonuc2 = null; //Cannot convert null to 'bool' because it is a value type
.NET 2.0 ile birlikte bu sorun aşıldı ve değer türlerinin null değerini alabilmeleri sağlandı. Generic tip temelini kullanan bu türler, nullable(null değer alabilen) olarak tanımlanır.
VB.NET tarafında Int, char, double gibi değer türlerini nullable yapabilmek için değişkenler, System.Nullable(Of T As Structure) türünde tanımlanır. Burada T parametresi değer türünün adını temsil eder. Aşağıdaki satırlarda null değer alabilen üç farklı değer türünde değişken tanımlanmıştır;
Dim Tarih As Nullable(Of DateTime) Dim Yas As Nullable(Of Integer) Dim Sonuc As Nullable(Of Boolean)
C# tarafında Int, char, double gibi deÄŸer türlerini nullable yapabilmek için türün yanına “?” simgesi eklenir. AÅŸağıdaki satırlarda null deÄŸer alabilen üç farklı deÄŸer türünde deÄŸiÅŸken tanımlanmıştır;
DateTime? Tarih = null; int? Yas = null; bool? Sonuc = null;
Nullable deÄŸer türlerinin deÄŸer içerip içermediÄŸini kontrol etmek için System.Nullable structure’in HasValue property’si kullanılır.
If Tarih.HasValue Then
'İşlem
End If
if (Tarih.HasValue)
{
//İşlem
}
Nullable değer türleriyle ilgili diğer notlar aşağıda özetlenmiştir;
Referans türleri halihazırda null değeri desteklediği için nullable türünde tanımlamazlar.
Nullable değişkeninin değerini denetlemek için GetValueOrDefault() metodu ve HasValue, Value propertyleri kullanılır. System.Nullable.GetValueOrDefault() metodu, nullable türünün null(Nothing) olduğu durumlarda o anki veya default değerini döndürür.
Dim X As Nullable(Of Integer) = 10
Dim Y As Nullable(Of Integer) = 20
Console.WriteLine("X:[{0}] , Y:[{1}]", X, Y) 'X:[10] , Y:[20]
Y = X.GetValueOrDefault()
Console.WriteLine("X:[{0}] , Y:[{1}]", X, Y) 'X:[10] , Y:[10]
X = Nothing
Y = X.GetValueOrDefault()
Console.WriteLine("X:[{0}] , Y:[{1}]", X, Y) 'X:[] , Y:[0]
X = 10 : Y = 20
Console.WriteLine("X:[{0}] , Y:[{1}]", X, Y) 'X:[10] , Y:[20]
Y = X.GetValueOrDefault(15)'Default değer atanmıştır
Console.WriteLine("X:[{0}] , Y:[{1}]", X, Y) 'X:[10] , Y:[10]
X = Nothing
Y = X.GetValueOrDefault(14)
Console.WriteLine("X:[{0}] , Y:[{1}]", X, Y) 'X:[] , Y:[14]
int? X = 10;
int? Y = 20;
Console.WriteLine("X:[{0}] , Y:[{1}]", X, Y); //X:[10] , Y:[20]
Y = X.GetValueOrDefault();
Console.WriteLine("X:[{0}] , Y:[{1}]", X, Y); //X:[10] , Y:[10]
X = null;
Y = X.GetValueOrDefault();
Console.WriteLine("X:[{0}] , Y:[{1}]", X, Y); //X:[] , Y:[0]
X = 10 ; Y = 20;
Console.WriteLine("X:[{0}] , Y:[{1}]", X, Y); //X:[10] , Y:[20]
Y = X.GetValueOrDefault(15);//Default değer atanmıştır
Console.WriteLine("X:[{0}] , Y:[{1}]", X, Y); //X:[10] , Y:[10]
X = null;
Y = X.GetValueOrDefault(14);
Console.WriteLine("X:[{0}] , Y:[{1}]", X, Y); //X:[] , Y:[14]
Nullable deÄŸer türlerinin Value property’si read-only olup deÄŸiÅŸkenin null olmadığı durumdaki deÄŸerini döndürür. DeÄŸiÅŸken, null iken value property’si çaÄŸrıldığı zaman System.InvalidOperationException hatası oluÅŸur.
Konuyla ilgili olarak C# tarafında birkaç madde daha yazabiliriz;
Nullable ile non-nullable türler arasında büyüklük ve küçüklük durumlarına göre implicit veya explicit dönüşüm yapılabilir;
int StandardInteger = 45; int? NullableInteger; decimal StandardDecimal = 2.75M; // Int -> Int? implicit dönüşüm NullableInteger = StandardInteger; //Int? -> Int explicit dönüşüm StandardInteger = (int)NullableInteger; //Decimal -> Int? explicit döünşüm NullableInteger = (int?)StandardDecimal;
Nullable numerik türündeki değişkenler üzerinde aritmetik işlemler yapıldığı zaman değişkenlerin null olup olmamasına bağlı olarak sonuç değişir;
int? X = 15; int? Y = null; int? Sonuc; Sonuc = X * 3; //Sonuc = 45 Sonuc = X * Y; //Sonuc= null
C# tarafındaki diÄŸer önemli geliÅŸme nullable deÄŸiÅŸkenler için “??” operatörünün(Null Coalescing Operator) geliÅŸtirilmiÅŸ olmasıdır. Bu operatör, uygulandığı deÄŸiÅŸkenin null olup olmadığını kontrol eder eÄŸer null ise koÅŸulda verilmiÅŸ deÄŸer deÄŸilse deÄŸiÅŸkenin oanki deÄŸeri geriye döndürülür.
int? X = 10;int Y;
Y = X ?? 15;
Console.WriteLine("X:[{0}] , Y:[{1}]", X, Y); //X:[10] , Y:[10]
X = null;
Y = X ?? 15;
Console.WriteLine("X:[{0}] , Y:[{1}]", X, Y); //X:[] , Y:[15]




Kasım 25th, 2008 at 02:18
Nullable veri tipi kullanmanın performansa bir etkisi varmı
Kasım 25th, 2008 at 11:12
Bu soru birçok programcıyı meÅŸgul etmiÅŸtir. Bu konuda detaylı test yapmamış olsam da kabaca ÅŸunu söyleyebiliriz. Bu türlerin doÄŸaları itibariyle deÄŸer türleri(value type) kadar performanslı olması beklenmemeli. Nullable türleri üzerinde iÅŸlemler yapılacak deÄŸiÅŸkenler için kullanmak pek mantıklı olmaz. EÄŸer mutlaka iÅŸlem yapılacaksa HasValue özelliÄŸinin kullanılarak deÄŸerinin normal bir deÄŸer türüne aktarılması performansı iyileÅŸtirebilir. Bu türleri veritabanı iÅŸlemlerinde tercih etmek daha doÄŸru olacaktır. Yine de stack tabanlı olmalarından dolayı Nullable deÄŸiÅŸkenlerin daha önce kullanılan “boxed value type” yönteminden daha performanslı ve kullanışlı olduÄŸunu söyleyebiliriz.