| YAZAR HAKKINDA |
http://www.buraksenyurt.com
İletişme geçmek için
tıklayın.
303 Makalesi yayınlanmakta.
Yazar hakkında detaylı bilgi için
tıklayın.
Yayınlanan diğer makaleleri için
tıklayın.
|
| |
| YAZI HAKKINDA |
| Türü |
: Makale
|
| Seviyesi |
: Orta |
| Kategori |
: C# / VC#/.NET |
| Yayınlanma Tarihi |
: 6/23/2005 |
| Okunma Sayısı |
: 8700 |
| Yorum Sayısı |
: 2
yorum yaz
|
|
SİTE
İÇİ ARAMA |
|
|
Blogroll |
|
|
|
|
|
|
C# 2.0 ve Nullable Değer Tipleri |
|
| Gönderiliyor lütfen bekleyin... |
|
|
C# programlama dilinde bildiğiniz gibi
veri türlerini Referans Türleri(Reference Types) ve Değer Türleri (Value
Types) olmak üzere iki kısma ayırıyoruz. Bu iki tür arasında bellek
üzerinde fiziki tutuluş şekillerinden tutunda birbirleri arasındaki
atamalara kadar pek çok farklılık vardır. Bu farklılıklardan birisi de,
referans türlerinin null değerleri alabilmelerine karşın, değer
türlerinin aynı özelliğe sahip olmayışlarıdır. Bu durum özellikle veritabanı
tablolarında null değer alabilen alanların, dil içerisindeki tip
karşılığı değer türüne denk düştüğünde bazı zorluklar
çıkartabilmektedir. İşte bu makalemizde, C# 2.0 diliyle gelen yeni
özelliklerden birisi olan Nullable Value Types (Null değer alabilen
değer türleri) ni incelemeye çalışacağız. Başlangıç olarak C#
1.1 versiyonundaki durumu analiz ederek işe başlayalım. Aşağıdaki kod parçasında bir
referans türüne ve bir de değer türüne null değerler atanmaya
çalışılmaktadır.
using System;
namespace ConsoleApplication2
{
class Class1
{
static void Main(string[] args)
{
string
refTuru=null;
int
degerTuru=null;
}
}
} |
Bu uygulamayı derlemeye çalıştığımızda
Cannot convert null to int because it is a value type hatasını
alırız. Aynı durumu kendi tanımladığımız referans ve değer türleri
içinde gerçekleştirebiliriz. Aşağıdaki kod parçasında bu durum
örneklenmiştir.
using System;
namespace ConsoleApplication2
{
class Kitap
{
}
struct Dvd
{
}
class Class1
{
static void Main(string[] args)
{
Kitap
kitap=null;
Dvd
dvd=null;
}
}
} |
Bu kod parçasındada aynı hatayı alırız.
Çünkü struct lar değer türüdür ve bu sebeple null değerler alamazlar.
Oysaki aynı istisnai durum class gibi kendi tanımlamış olduğumuz
referans türleri için geçerli değildir. Peki değer türlerinin null değer
içerme ihtiyacı ne zaman doğabilir? Bir veritabanı uygulamasını göz
önüne alalım. Bu tabloda int, double gibi değer türlerine karşılık
gelecek alanların var olduğunu düşünelim. Veri girişi sırasında bu int
ve double değişkenleri null olarak tabloya aktarmak isteyebiliriz. Ya da
tablodan veri çekerken, değer türü karşılığı alanların null değer içerip
içermediğini anlamak isteyebiliriz. İşte bu gibi durumlarda değer
türlerinin null veriler içerebilecek yapıda olması, kodumuzun ölçeklenebilirliğini
arttıracak bir yetkinlik olarak düşünülebilir. Veritabanları için
geçerli olan bu senaryoyu göz önüne almadan önce C# 2.0 için
değer türlerinin nasıl null veriler taşıyabileceğini incelemeye
çalışalım. Değer türlerinin C# 2.0 için iki versiyonu vardır. Nullable
değer türleri ve Non-Nullable değer türleri. Bir değer türünün null
değerler içerecek tipte olacağını belirtmek için ? tip belirleyicisi
kullanılır.
using System;
using System.Collections.Generic;
using System.Text;
namespace TestOfNullableValues
{
class Program
{
static void Main(string[] args)
{
int?
maas;
double?
pi;
maas = null;
pi = null;
}
}
} |
Yukarıdaki kod parçası sorunsuz olarak
derlenecek ve çalışacaktır. ? ile tanımlanan değer türleri null veriler
taşıyabilen değer tipindendir. Aynı durum kendi tanımladığımız bir struct içinde
geçerlidir. Aşağıdaki kod parçasında Personel isimli struct a null
değer ataması yapılmıştır.
struct Personel
{
}
class Program
{
static void Main(string[] args)
{
Personel? person = null;
}
} |
Elbette referans türlerinde bu tarz bir
kullanım geçerli olmayacaktır. Örneğin aşağıdaki kod parçasında kendi
tanımlamış olduğumuz bir sınıf nesnesine ve string türünden bir
değişkene ? belirleyicisi vasıtasıyla null değerler atanmaya
çalışılmıştır.

Oysaki referans türleri zaten null
değerler alabilmektedir.
 |
Referans türlerine ? tip
belirleyicisi uygulayarak null değer ataması yapılamaz. |
? tip belirleyicisi aslında tanımlanan
değer türünün null veri taşıyabilecek başka bir versiyonunu
kullanılacağını belirtmektedir. Bu yeni değer türü versiyonları ise null
verileri taşıyabilecek bir yapıda tasarlanmışlardır. ? belirleyicisinin
uygulandığı bir değer türünün null değerler içerip içermediğine
HasValue özelliği ilede bakılabilmektedir. Bu özellik, ilgili değer
türü null veri içerdiği sürece false döndürecektir. Örneğin,
int? Yas;
Yas = null; // Yas değer türüne null veri atanıyor.
if (Yas.HasValue) // false dönecektir
{
Console.WriteLine("Yas null değil...");
}
else
{
Console.WriteLine("Yas null..."); // Bu satır işletilir.
} |
C# 2.0 diline ? tip belirleyicisinden
yola çıkılaraktan yeni bir operatör eklenmiştir. ?? operatörü. Bu
operatör kısaca bir değer türünün içeriğinin null olup olmamasına göre
koşullu olarak atama yapmaktadır. Eğer operatörde kullanılan null veri
taşıyabilir değer türünün o anki değeri null ise, koşul olarak
belirtilen değer ilgili değişkene atanır. Aksi takdirde, değer türünün o
anki verisi, ilgili değişkene atanır. Aşağıdaki örnek kod parçasında bu
operatörün kullanım şekli gösterilmeye çalışılmıştır.
int? Yas; // null değer
alabilecek bir değer türü tanımlanıyor.
Yas = null; // null değer ataması
int yasi = Yas ?? 0; // Eğer Yas null ise yasi alanına 0
atanır.
Console.WriteLine(yasi); // 0 yazar
Yas = 12;
yasi = Yas ?? 0; // Eğer Yas null değil ise yasi alanına
Yas ın o anki değeri atanır.
Console.WriteLine(yasi); // 12 yazar |
İlk kullanımda, Yas değer türünün sahip
olduğu veri null olarak belirlenmiştir. ?? operatörü bu durumda yasi
alanına 0 değerini atayacaktır. İkinci kullanımda ise Yas değer türünün
verisi 12 olarak belirlenmiştir. Buna görede ?? operatörü yasi
değişkenine 12 değerini (yani Yas nullable değer türünün o anki
verisini) atayacaktır. Burada dikkat ederseniz Yas null değer alabilen
bir int tipidir. Bununla birlikte ?? operatörü ile yapılan veri ataması
null değerler içeremiyen normal bir int tipine doğru yapılmaktadır.
Burada söz konusu olan atama işlemini biraz irdelemekte fayda vardır.
Aşağıdaki kod parçasını ele alalım.
int? pi = 3;
int m_Pi;
m_Pi = pi; |
Bu örnek derlenmeyecektir. Bunun sebebi
ise null değer alabilen bir değer türünü, normal bir değer türüne
bilinçsiz olarak atamaya çalışmamızdır. Dolayısıyla,
 |
Nullable Değer türleri
bilinçsiz olarak normal değer türlerine dönüştürülemez. |
Ancak aşağıdaki kod parçasında görülen
tür dönüşüm işlemi geçerlidir.
int? pi = 3;
int m_Pi;
m_Pi = (int)pi; |
Elbette burada dikkat edilmesi gereken
bir durum daha vardır. Eğer o anki değeri null olan bir değer türünü
normal bir değer türüne bilinçli olarak atamaya çalışırsak çalışma
zamanında InvalidOperationException hatası alırız.

Dolayısıyla bu tip atamalarda ??
operatörünü tercih etmek çok daha akılcı bir yaklaşım olacaktır.
Nullable değer türlerine, normal değer türlerinin atanmasında ise
bilinçsiz tür dönüşümü de geçerlidir.
double e = 2.7;
double? E;
E = (double?)e; // Bilinçli tür dönüşümü
E = e; // Bilinçsiz tür dönüşümü |
Yukarıdaki kod parçasında E null
değerler taşıyabilen bir değer türüdür. e ise normal değer türüdür.
 |
Normal değer türleri,
nullable değer türlerine hem bilinçli hem de bilinçsiz olarak
dönüştürülebilir. |
Makalemizin sonunda bir veritabanı
uygulamasında null değerler alabilen değer türlerinin nasıl
kullanılabildiğini incelemeye çalışacağız. İlk olarak C# 1.1
versiyonunda aşağıdaki yapıda bir uygulama geliştirelim. Bu örneğimizde,
Sporculara ait bir takım temel bilgileri tutan bir tabloyu kullanacağız.
Tablomuzda tanımlı olan Sporcu, Boy ve Yaş alanları null değerler
içerebilecek şekilde yapılandırılmıştır.

Örnek olarakta aşağıdaki iki satır
verinin var olduğunu düşünelim. Dikkat ederseniz ikinci satırda değer
türü olarak ele alacağımız alanlara <Null> değerler atanmıştır.

Uygulama kodlarımız ise başlangıç
olarak aşağıdaki gibidir. Basit olarak Sporcuları temsil edecek bir
sınıf ve tablo üzerindeki temel veritabanı işlemlerini gerçekleştirecek
bir katman sınıfı yer almaktadır. Katman sınıfımız şu an için sadece ve
sadece Sporcu tablosundaki verileri okuyup, her bir satır için birer
Sporcu nesnesi yaratan ve onun override edilmiş ToString metodu ile
bilgilerini ekrana yazdıran bir metoda sahiptir.
using System;
using System.Data;
using System.Data.SqlClient;
namespace TestNullableValues
{
class Sporcu
{
private int m_id;
private string m_sporcu;
private double m_boy;
private int m_kilo;
public Sporcu(int id,string
sporcu,double boy,int kilo)
{
m_id=id;
m_sporcu=sporcu;
m_boy=boy;
m_kilo=kilo;
}
public override string ToString()
{
return
m_id.ToString()+" "+m_sporcu+" "+m_boy.ToString()+"
"+m_kilo.ToString();
}
}
class SporYonetim
{
SqlConnection con;
SqlCommand cmd;
SqlDataReader dr;
public SporYonetim()
{
con=new
SqlConnection("data source=localhost;database=MyBase;user
id=sa;password=");
}
public void SporcuListesi()
{
cmd=new
SqlCommand("Select ID,Sporcu,Boy,Kilo From Sporcular",con);
con.Open();
dr=cmd.ExecuteReader(CommandBehavior.CloseConnection);
while(dr.Read())
{
int id=(int)dr["ID"];
string sporcu=dr["Sporcu"].ToString();
double boy=(double)dr["Boy"];
int kilo=(int)dr["Kilo"];
Sporcu sprc=new Sporcu(id,sporcu,boy,kilo);
Console.WriteLine(sprc.ToString());
}
}
}
class Class1
{
[STAThread]
static void Main(string[] args)
{
SporYonetim
ynt=new SporYonetim();
ynt.SporcuListesi();
}
}
} |
Bizim için önemli olan nokta Boy ve Yas
alanlarının değererinin double ve int alanlara atıldığı yerdir.
Uygulamamızı bu haliyle çalıştırdığımızda aşağıdaki hata mesajını
alırız.
Sebep gayet net ve açıktır. Değer türleri
null veri içeremeyeceği için cast işlemleri çalışma zamanında
InvalidCastException tipinden bir istisna nesnesi fırlatılmasına neden
olmuştur. Bu sorunu aşmak için kullanabileceğimiz tekniklerden bir
tanesi aşağıdaki gibidir. dr ile okunan tablo alanları object tipinden
geriye döndüğünden ve object tipide referans türü olduğundan null
değerler içerebilir. Burada alanın o anki verisinin null olup olmamasına
göre uygun atamalar gerçekleştirilmektedir.
double boy;
int kilo;
if(dr["Boy"]==System.DBNull.Value)
boy=0;
else
boy=(double)dr["Boy"];
if(dr["Kilo"]==System.DBNull.Value)
kilo=0;
else
kilo=(int)dr["Kilo"];
Sporcu sprc=new Sporcu(id,sporcu,boy,kilo); |
Aynı örneği aşağıdaki haliyle C#
2.0 versiyonunda daha farklı bir yaklaşım ile yazabiliriz. Bu kez,
Sporcu sınıfımızın yapıcı metodunda yer alan boy ve kilo parametleri ile
private field olarak tanımladığımız m_Boy ve m_Kilo alanlarını null değer
içerebilecek şekilde tanımlayarak işe başlayacağız. Yine SqlDataReader
ile okuduğumuz alanların null değer içerip içermediğini kontrol
edeceğiz. Ancak bu kez null değer içerseler dahi onları taşayabilecek
değer türlerimiz elimizde olacak. Böylece tablomuzda null değere sahip
olan alanlarımızı ekrana yazdırabileceğiz.
using System;
using System.Data;
using System.Data.SqlClient;
using System.Collections.Generic;
using System.Text;
namespace UsingNullableValues
{
class Sporcu
{
//Diğer kod satırları
// Sınıf içi bu iki alanı null
değerler taşıyabilecel tipten tanımladık.
private double? m_boy;
private int? m_kilo;
// Diğer kod satırları
}
class SporYonetim
{
// Diğer kod satırları
public void SporcuListesi()
{
// Diğer kod
satırları
while
(dr.Read())
{
// Diğer kod satırları
double? boy=null;
int? kilo=null;
if(dr["Boy"]!=System.DBNull.Value)
boy=(double)dr["Boy"];
if (dr["Kilo"] != System.DBNull.Value)
kilo = (int)dr["Kilo"];
// nullable değişkenleri Sporcu sınıfının yapıcı metoduna
parametre olarak gönderiyoruz.
Sporcu sprc = new Sporcu(id, sporcu, boy, kilo);
Console.WriteLine(sprc.ToString());
}
}
}
class Program
{
static void Main(string[] args)
{
SporYonetim
ynt = new SporYonetim();
ynt.SporcuListesi();
}
}
} |
Uygulamamızı bu haliyele çalıştırdığımızda
tablodaki tüm satırların ekrana yazdırıldığını görürüz. C# 1.1 de
geliştirdiğimiz uygulama ile bu versiyon arasındaki en önemli fark,
nullable değer türlerinin kullanılarak null verilerin uygulama
içerisinde kullanılabilmesidir. Bir sonraki makalemizde görüşmek
dileğiyle hepinize mutlu günler dilerim.
Burak Selim ŞENYURT
selim@bsenyurt.com
alabilen,belirleyicisi,degerler,double,main(string[],normal,nullable,private,public,referans,sporcu,static,string,vardir.,veritabani, C# / VC#/.NET, Burak Selim Şenyurt C# 2.0 ve Nullable Değer Tipleri C#, Visual C# ve .NET Burak Selim Şenyurt
|
|
NİS 7
2006 |
Evet gerçektende C# 2.0 örneğinde yine if kontrolü yapılıp alanların Null değer taşıyıp taşımadığına bakılıyor. Ancak buradaki gelişme bu kontrol mekanizamsı değil, değer türlerinin null veri içerip çalışabilmesine olanak sağlanmış olmasıdır. Dolayısıyla yeni eklenen bu özelliği bu şekilde bakarsak daha yararlı olacaktır kanısındayım. |
|
EYL 11
2005 |
Tür bönüşümleri konusunda bir çözüm göremedim. Veritabanından gelen değerleri nesneye çevirirken if-then-else kullanacaksak ne anlamı varki bu gelişmenin?
Makalenizde bu konulara değinmemişsiniz. |
|
|
Sayfalar :
|
|
|
|
|
|
|
-
-
Eklenen Son 10
-
Bu Konuda Geçmiş 10
Bu Konuda Yazılmış Yazılmış 10 Makale Yükleniyor
Son Eklenen 10 Makale Yükleniyor
Bu Konuda Yazılmış Geçmiş Makaleler Yükleniyor
|
|
|
|