C# Boxing ve Unboxing İşlemleri
C# severlere merhabalar
Önceki makalelerimizde C#.Net’te döngüleri görmüştük ancak döngülere biraz ara verip farklı konulara girip .Net mimarisini keşfedeceğiz.
Bugünkü makalemizin konusu C# ile boxing (kutulama) ve unboxing (kutudan çıkarma) olayları,bu iki konuyu öğrenmek için öncelikle .net framework mimarisi üzerine sohbet edelim.
.Net framework mimarisi tamamen nesne tabanlı bir yapıdan oluşmaktadır ve kod olarak yazdığımız birçok özellik gerçek dünyadaki nesnelerden esinlenerek tasarlanmıştır.Dolayısıyla int,string gibi değer tipleri ve ileriki makalelerde göreceğimiz referans tipler birer nesneye karşılık gelmektedir.
Madem tüm mimari nesneler üzerine kuruluysa sanki gerçek dünyadaki nesneler gibi üzerlerinde bazı işlemler yapılabilir,tabi kuralına uymak koşuluyla!
Örneğin; evimizde bir vazo var ve biz vazoyu kırılmasın diye kutuya koyuyor bir başka yere taşıyor ve kutusundan çıkarıp yeniden kullanmaya devam ediyoruz.İşte .net mimarisini kuran yazılımcılar tıpkı gerçek hayatta bu gibi olayları hayal ederek boxing ve unboxing işlemlerini ortaya çıkarmışlar.
Öncelikle boxing konusunu anlamaya çalışalım;
Boxing kelimesini Türkçe’ye çevirdiğimizde “kutulama” ya da “kutuya koyma” gibi bir anlama geliyor,peki yazılımsal nesneleri nasıl kutulayacağız?
Şimdiye kadar makalelerimizde değer tiplerinden hep string,int,bool.. gibi nesneleri kullanarak değişkenler tanımladık.Bu ve bu gibi değişken tiplerinin kaynağı System.Object sınıfından gelmektedir.Yani .net framework mimarisinde sayı (int,double..), metin(string),karakter(char) gibi herşeyin özünde nesnesellik (object) kavramı yatmaktadır.
Madem herşey objeden geliyor bu durumda her şeyi objeye geri döndürmek mümkün,bu cümle biraz “topraktan geldik yine toprağa döneceğiz” gibi bir şeye benzedi ama neredeyse aynı şeyler diyebiliriz.
Diyelim elimizde int sayi=5; değişkenimiz var, integer değişken tipi diğer değer tipleri gibi System.Object sınıfından geliyorsa demek ki 5 sayısını nesne değişken tipi olan “object” değişkenine yükleyebiliriz.Böylece;
int sayi=5;
object nesne=sayi;
olma şansına sahip oluyor.
Dikkat ederseniz sayısal bir değişkeni bir başka değişkene yüklerken daha önce değişken dönüşümlerinde olduğu gibi Convert işlemi uygulamadık,bunun nedeni int değişken tipinin zaten object (nesne) in kendisi olmasından kaynaklanıyor.O yüzden Convert sınıfında ToObject diye bir metotta yoktur!
Yukarıdaki işleme tekrar bakarsak;
object nesne=sayi;
Satırında sayi değişkenini object değişkenine yükledik,işte bu yükleme olayına boxing (kutulama) işlemi denilmektedir.Gerçek dünya gibi hayal edersek 5 sayısını object kutusunun “içine” koyduk ve bu nesne adındaki object değişkenini daha sonra istediğimiz heryerde kullanabiliriz,öyle ki 5 sayısını string ifadeye çevirmek bile mümkün.
Peki int değişken tipindeki bir ifadeyi object tipine kutuladıktan sonra nasıl tekrar kutudan çıkaracağız.Tam bu noktada yep yeni bir kavramla karşılaşıyoruz: casting!
Casting kavramını Türkçe’ye tam olarak çeviremiyoruz ancak kabaca tarif etmek gerekirse herhangi bir nesneye anlam katmak diyebiliriz.
Cast edilecek ifadeyi bir başka ifadeye anlamlandırmanın iki yolu bunlardan biri ifadenin yanında parantez açıp (degiskentipi) yazarak,diğer yolu da ifadenin sağına “as ifadetipi” yazarak gerçekleştiriliyor.
Şimdi tekrar boxing-unboxing konusuna geri dönersek kutuladığımız bir ifadenin boxing işleminden sonra son hali;
object nesne=5;
oluyor.
Daha önce integer olan bu 5 sayısını object değişkeninden tekrar sayısal tipe çevirmek istersek şu şekilde yazıyoruz:
int yeniSayi=(int) nesne;
Bu durumda int yeniSayi=5; oldu,çünkü “nesne” ifadesi zaten 5 sayısını barındırıyordu.Parantez içerisinde yazdığımız int değişken tipi ise “nesne” isimli ifadenin zaten int tipi olduğunu tanımlıyor,yani casting işlemini gerçekleştirdik.
Object değişken tipi olan int sayısını yukarıdaki gibi değilde casting işleminin ikinci ifadesi olarak yapmak isteseydik;
int yeniSayi=nesne as int;
Şeklinde yazabilirdik.Değişen tek şey parantez içerisinde (int) yazmak yerine “as int” yazarak kutudan çıkarma işlemini gerçekleştirdik.
Peki bu kadar kutulama,kutudan çıkarma ve cast işlemi neden yapılıyor? Bildiğimiz şekilde int,string gibi tanımlamalar işimizi görmüyor mu?
Maalesef yazılım dünyası çok karmaşık olduğu için her yerde int,string gibi değişken tiplerini bu kadar basit kullanamıyoruz,öyle ki veritabanı ya da harici bir dosya gibi kaynaklar içerisinden çağırdığımız verinin tipini doğrudan değişkene atamayabiliyoruz çünkü veri çok karmaşık olduğu için bazı işlemlerden geçmesi gerekebiliyor.Dolayısıyla gelen veriyi cast etmek durumunda kalabileceğimiz gibi .net mimarisini daha iyi anlamak adına bu şekilde düşünerek doğru ve performanslı algoritmalar kurabiliriz.
Dikkat çektiğim bir diğer önemli konu ise casting işlemiyle ilgili; bahsettiğim gibi casting işlemleri değişkenleri yeniden tanımlamamızı sağlıyor ancak yanlış tanımlamalar tehlikeli veri kayıplarına sebep olmaktadırlar.
Örneğin uint tipinde bir değişkeni int16 tipine cast ettiğimiz anda veri kaybı yaşarız çünkü uint değişken tipi int16 tipine göre daha yüksek sayı kapasitesine sahip ancak uint değişken tipindeki değeri int16 değişkenine cast ettiğimizde elimizdeki sayının en büyük değeri artık int16 veri tipiyle sınırlı kalacaktır,yani int16 değişkeni sadece alabileceği kadar veriyi üstlenmiş olacak gerisini çöpe atacaktır.
Bu konuya yazılımda bilinçlilik ve bilinçsizlik denilmektedir; bilinçli yaptığımı cast işlemi gibi bilerek yaptığımız ve veri kaybı riskinin farkında olduğumuz işlemler, bilinçsiz ise Convert.ToInt32 metodunu kullanarak kontrolü tamamen bilgisayar denetimine bırakmaktadır.
Bu makalemizde .net framework mimarisini bu kadar kolay anlamak elbette mümkün değil çünkü ortada bir mimariden bahsediyoruz yani karşımızda birkaç satır kod yok.
Şu ana kadar mimarinin nereden ne şekilde geldiğini anladık ve ilerleyen C# makalelerimizde,özellikle veritabanından veri çağırma gibi işlemlerde casting işlemini kullanacağız.Object konusu ise hem casting konusunu anlamamıza yardımcı olduğu gibi hem de ileride göreceğimiz referans tipleri öğrenmemize yardımcı olacak.
Peki boxing ve unboxing işlemlerini yapmadan doğrudan object sınıfını kullanamaz mıydık?
Tabiki mümkün,örneğin aşağıda bir kelimeyi string biçimde tutmak yerine object tipinde kullanabiliriz:
string kelime=”kalem”;
yerine
object kelime=”kalem”;
şeklinde kullanabiliriz,ancak bu derece basit kullanım sonucunda bizden string biçimde bir ifade bekleyen metotlarda object nesnesini yeniden string ifadeye cast etmek zorunda kalırız.Mesela messagebox.show() metodu üzerinden bir örnek yapalım;
string kelime=”kalem”;
MessageBox.Show(kelime);
Bu şekilde yaptığımız şu ana kadar öğrendiğimiz yapıydı ve aynı yapıyı
object kelime=”kalem”;
MessageBox.Show((string) kelime);
şeklindede kullanabiliriz ama casting yaparak gereksiz zaman harcayarak ve gereksiz fazladan kod yazmış oluruz.Dolayısıyla C# ya da VB.Net gibi .Net Framework mimarisiyle desteklenmiş dillerde her değer hangi değişken tipiyle kolaylıkla tanımlanıyorsa o şekilde yazmak daha doğrusu olacaktır.
Bu makalemiz umarım .net framework mimarisinin özünü kavramanıza yardımcı olmuştur,bir sonraki makalemizde görüşmek dileğiyle hoşçakalın.
Önceki makalelerimizde C#.Net’te döngüleri görmüştük ancak döngülere biraz ara verip farklı konulara girip .Net mimarisini keşfedeceğiz.
Bugünkü makalemizin konusu C# ile boxing (kutulama) ve unboxing (kutudan çıkarma) olayları,bu iki konuyu öğrenmek için öncelikle .net framework mimarisi üzerine sohbet edelim.
.Net framework mimarisi tamamen nesne tabanlı bir yapıdan oluşmaktadır ve kod olarak yazdığımız birçok özellik gerçek dünyadaki nesnelerden esinlenerek tasarlanmıştır.Dolayısıyla int,string gibi değer tipleri ve ileriki makalelerde göreceğimiz referans tipler birer nesneye karşılık gelmektedir.
Madem tüm mimari nesneler üzerine kuruluysa sanki gerçek dünyadaki nesneler gibi üzerlerinde bazı işlemler yapılabilir,tabi kuralına uymak koşuluyla!
Örneğin; evimizde bir vazo var ve biz vazoyu kırılmasın diye kutuya koyuyor bir başka yere taşıyor ve kutusundan çıkarıp yeniden kullanmaya devam ediyoruz.İşte .net mimarisini kuran yazılımcılar tıpkı gerçek hayatta bu gibi olayları hayal ederek boxing ve unboxing işlemlerini ortaya çıkarmışlar.
Öncelikle boxing konusunu anlamaya çalışalım;
Boxing kelimesini Türkçe’ye çevirdiğimizde “kutulama” ya da “kutuya koyma” gibi bir anlama geliyor,peki yazılımsal nesneleri nasıl kutulayacağız?
Şimdiye kadar makalelerimizde değer tiplerinden hep string,int,bool.. gibi nesneleri kullanarak değişkenler tanımladık.Bu ve bu gibi değişken tiplerinin kaynağı System.Object sınıfından gelmektedir.Yani .net framework mimarisinde sayı (int,double..), metin(string),karakter(char) gibi herşeyin özünde nesnesellik (object) kavramı yatmaktadır.
Madem herşey objeden geliyor bu durumda her şeyi objeye geri döndürmek mümkün,bu cümle biraz “topraktan geldik yine toprağa döneceğiz” gibi bir şeye benzedi ama neredeyse aynı şeyler diyebiliriz.
Diyelim elimizde int sayi=5; değişkenimiz var, integer değişken tipi diğer değer tipleri gibi System.Object sınıfından geliyorsa demek ki 5 sayısını nesne değişken tipi olan “object” değişkenine yükleyebiliriz.Böylece;
int sayi=5;
object nesne=sayi;
olma şansına sahip oluyor.
Dikkat ederseniz sayısal bir değişkeni bir başka değişkene yüklerken daha önce değişken dönüşümlerinde olduğu gibi Convert işlemi uygulamadık,bunun nedeni int değişken tipinin zaten object (nesne) in kendisi olmasından kaynaklanıyor.O yüzden Convert sınıfında ToObject diye bir metotta yoktur!
Yukarıdaki işleme tekrar bakarsak;
object nesne=sayi;
Satırında sayi değişkenini object değişkenine yükledik,işte bu yükleme olayına boxing (kutulama) işlemi denilmektedir.Gerçek dünya gibi hayal edersek 5 sayısını object kutusunun “içine” koyduk ve bu nesne adındaki object değişkenini daha sonra istediğimiz heryerde kullanabiliriz,öyle ki 5 sayısını string ifadeye çevirmek bile mümkün.
Peki int değişken tipindeki bir ifadeyi object tipine kutuladıktan sonra nasıl tekrar kutudan çıkaracağız.Tam bu noktada yep yeni bir kavramla karşılaşıyoruz: casting!
Casting kavramını Türkçe’ye tam olarak çeviremiyoruz ancak kabaca tarif etmek gerekirse herhangi bir nesneye anlam katmak diyebiliriz.
Cast edilecek ifadeyi bir başka ifadeye anlamlandırmanın iki yolu bunlardan biri ifadenin yanında parantez açıp (degiskentipi) yazarak,diğer yolu da ifadenin sağına “as ifadetipi” yazarak gerçekleştiriliyor.
Şimdi tekrar boxing-unboxing konusuna geri dönersek kutuladığımız bir ifadenin boxing işleminden sonra son hali;
object nesne=5;
oluyor.
Daha önce integer olan bu 5 sayısını object değişkeninden tekrar sayısal tipe çevirmek istersek şu şekilde yazıyoruz:
int yeniSayi=(int) nesne;
Bu durumda int yeniSayi=5; oldu,çünkü “nesne” ifadesi zaten 5 sayısını barındırıyordu.Parantez içerisinde yazdığımız int değişken tipi ise “nesne” isimli ifadenin zaten int tipi olduğunu tanımlıyor,yani casting işlemini gerçekleştirdik.
Object değişken tipi olan int sayısını yukarıdaki gibi değilde casting işleminin ikinci ifadesi olarak yapmak isteseydik;
int yeniSayi=nesne as int;
Şeklinde yazabilirdik.Değişen tek şey parantez içerisinde (int) yazmak yerine “as int” yazarak kutudan çıkarma işlemini gerçekleştirdik.
Peki bu kadar kutulama,kutudan çıkarma ve cast işlemi neden yapılıyor? Bildiğimiz şekilde int,string gibi tanımlamalar işimizi görmüyor mu?
Maalesef yazılım dünyası çok karmaşık olduğu için her yerde int,string gibi değişken tiplerini bu kadar basit kullanamıyoruz,öyle ki veritabanı ya da harici bir dosya gibi kaynaklar içerisinden çağırdığımız verinin tipini doğrudan değişkene atamayabiliyoruz çünkü veri çok karmaşık olduğu için bazı işlemlerden geçmesi gerekebiliyor.Dolayısıyla gelen veriyi cast etmek durumunda kalabileceğimiz gibi .net mimarisini daha iyi anlamak adına bu şekilde düşünerek doğru ve performanslı algoritmalar kurabiliriz.
Dikkat çektiğim bir diğer önemli konu ise casting işlemiyle ilgili; bahsettiğim gibi casting işlemleri değişkenleri yeniden tanımlamamızı sağlıyor ancak yanlış tanımlamalar tehlikeli veri kayıplarına sebep olmaktadırlar.
Örneğin uint tipinde bir değişkeni int16 tipine cast ettiğimiz anda veri kaybı yaşarız çünkü uint değişken tipi int16 tipine göre daha yüksek sayı kapasitesine sahip ancak uint değişken tipindeki değeri int16 değişkenine cast ettiğimizde elimizdeki sayının en büyük değeri artık int16 veri tipiyle sınırlı kalacaktır,yani int16 değişkeni sadece alabileceği kadar veriyi üstlenmiş olacak gerisini çöpe atacaktır.
Bu konuya yazılımda bilinçlilik ve bilinçsizlik denilmektedir; bilinçli yaptığımı cast işlemi gibi bilerek yaptığımız ve veri kaybı riskinin farkında olduğumuz işlemler, bilinçsiz ise Convert.ToInt32 metodunu kullanarak kontrolü tamamen bilgisayar denetimine bırakmaktadır.
Bu makalemizde .net framework mimarisini bu kadar kolay anlamak elbette mümkün değil çünkü ortada bir mimariden bahsediyoruz yani karşımızda birkaç satır kod yok.
Şu ana kadar mimarinin nereden ne şekilde geldiğini anladık ve ilerleyen C# makalelerimizde,özellikle veritabanından veri çağırma gibi işlemlerde casting işlemini kullanacağız.Object konusu ise hem casting konusunu anlamamıza yardımcı olduğu gibi hem de ileride göreceğimiz referans tipleri öğrenmemize yardımcı olacak.
Peki boxing ve unboxing işlemlerini yapmadan doğrudan object sınıfını kullanamaz mıydık?
Tabiki mümkün,örneğin aşağıda bir kelimeyi string biçimde tutmak yerine object tipinde kullanabiliriz:
string kelime=”kalem”;
yerine
object kelime=”kalem”;
şeklinde kullanabiliriz,ancak bu derece basit kullanım sonucunda bizden string biçimde bir ifade bekleyen metotlarda object nesnesini yeniden string ifadeye cast etmek zorunda kalırız.Mesela messagebox.show() metodu üzerinden bir örnek yapalım;
string kelime=”kalem”;
MessageBox.Show(kelime);
Bu şekilde yaptığımız şu ana kadar öğrendiğimiz yapıydı ve aynı yapıyı
object kelime=”kalem”;
MessageBox.Show((string) kelime);
şeklindede kullanabiliriz ama casting yaparak gereksiz zaman harcayarak ve gereksiz fazladan kod yazmış oluruz.Dolayısıyla C# ya da VB.Net gibi .Net Framework mimarisiyle desteklenmiş dillerde her değer hangi değişken tipiyle kolaylıkla tanımlanıyorsa o şekilde yazmak daha doğrusu olacaktır.
Bu makalemiz umarım .net framework mimarisinin özünü kavramanıza yardımcı olmuştur,bir sonraki makalemizde görüşmek dileğiyle hoşçakalın.
süper tşkler cok yardımcı oldu
Gayet anlaşılır bir anlatım. Teşekkürler.
benzetmelerine hayranım abi :)