Tip çevrimleri (type casting) , tip güvenli (type safe) bir platform
olan .NET Framework ile kod geliştirirken çok sık kullandığımız bir mekanizmadır.
Peki bu kadar çok kullandığımız bu mekanizmanın yapabileceklerini biliyor
musunuz? Bu makalede tip çevrimi konseptini, gizli ve açık çevrimleri tanıyacaksınız.
Sonra da kendi yazdığımız sınıflar için nasıl tür çevrimini implement ederiz?’i
öğreneceksiniz.
Tip Çevrimleri (Type Casting)
Bu yıl (2005) ocağını hepimiz hatırlarız. Hayatımıza ytl diye bir kavram
girdi yıl başında. Bütün herşeyi etkileyen bu değişim yazılım sektörünü de
büyük zahmetlere soktu. Önceden altı sıfırlı paramızdan bu altı sıfırın çıkarılması
neden yazılımları bu kadar etkiledi. Eskiden bol sıfırlı olarak çalışan yazılımlarımız
kuruş konseptine geçerken biraz zorlandılar.
Açık ve Gizli Çevrimler :
Bu sorunu aşmada çok sık kullandığımız ama çok kimseninde merak edip araştırmadığı
bir teknik hayatımızı kurtarabilirdi “Tip çevrimleri” . İsterseniz kavrama çok
alışık olmayan arkadaşlar için tip çevrimini örnekleyelim önce.
int i;
float f;
float f;
f = i; //(implicit) gizli tür çevrimi
i = (int)f; // (explicit) açık tür çerimi
i = (int)f; // (explicit) açık tür çerimi
Yukarıda görülebileceği gibi iki farklı türde i ve f değişkenlerimiz
var. Biz bunları bir birine atarken gizli ve açık tür değişimleri
yapabiliyoruz.
Kendi Sınıflarımız İçin Tip Çevrimi
Peki bu tür değişimlerini kendi sınıflarımız için implement edemez miyiz ? Gelin yukarıda bahsettiğim ytl problemini tür değişimleri ile çözelim.
Peki bu tür değişimlerini kendi sınıflarımız için implement edemez miyiz ? Gelin yukarıda bahsettiğim ytl problemini tür değişimleri ile çözelim.
Önce eski tl ile kullandığımız bir fonksiyonumuz olsun.
static int Topla(int a, int b)
{
return a + b;
}
{
return a + b;
}
İşlemin daha kolay anlaşılması için önce basit bir fonksiyon ile başlamak
istedim. Şimdi kendi ytl sınıfımızı oluşturalım. Ve bu sınıf int türü için aldığı
tl değerlerini ytl ye çevirsin gizli olarak. Ytl değerlerini ise gizli olarak
int’e çevirsin.
public class YTL
{
private uint lira;
public uint Lira { get { return lira; } }
{
private uint lira;
public uint Lira { get { return lira; } }
private ushort kurus;
public ushort Kurus { get { return kurus; } }
public ushort Kurus { get { return kurus; } }
public YTL(uint lira, ushort kurus)
{
if (kurus > 99)
throw new ArgumentException("Kuruş 99’dan büyük olamaz");
{
if (kurus > 99)
throw new ArgumentException("Kuruş 99’dan büyük olamaz");
this.lira = lira;
this.kurus = kurus;
}
this.kurus = kurus;
}
/// <summary>
/// tl’yi ytl’ye çevirir
/// </summary>
/// <param name="tl"></param>
/// <returns></returns>
static public implicit operator YTL(int tl)
{
if (tl < 0)
throw new ArgumentException("TL sıfırdan küçük olamaz");
/// tl’yi ytl’ye çevirir
/// </summary>
/// <param name="tl"></param>
/// <returns></returns>
static public implicit operator YTL(int tl)
{
if (tl < 0)
throw new ArgumentException("TL sıfırdan küçük olamaz");
YTL ytl = new YTL(0, 0);
ytl.lira = (uint)(tl / 1000000);
ytl.kurus = (ushort)((tl - ytl.lira * 1000000) / 10000);
ytl.lira = (uint)(tl / 1000000);
ytl.kurus = (ushort)((tl - ytl.lira * 1000000) / 10000);
if ((tl - ytl.lira * 1000000 - ytl.kurus * 10000) > 4999)
ytl.kurus++;
ytl.kurus++;
return ytl;
}
}
/// <summary>
/// ytl’yi tl’ye çevirir
/// </summary>
/// <param name="ytl"></param>
/// <returns></returns>
static public implicit operator int(YTL ytl)
{
return (int)(ytl.Lira * 1000000 + ytl.Kurus * 10000);
}
/// ytl’yi tl’ye çevirir
/// </summary>
/// <param name="ytl"></param>
/// <returns></returns>
static public implicit operator int(YTL ytl)
{
return (int)(ytl.Lira * 1000000 + ytl.Kurus * 10000);
}
}
Şimdi ise bu ytl sınıfını eski tl fonksiyonunda kullanalım.
YTL i = new YTL(1, 50);
YTL j = new YTL(2, 50);
YTL k = Topla(i, j);
int p = k;
Console.WriteLine(p.ToString());
Console.ReadLine();
YTL j = new YTL(2, 50);
YTL k = Topla(i, j);
int p = k;
Console.WriteLine(p.ToString());
Console.ReadLine();
Yukarıdaki satırlar sorun olmaksızın çalışır ve p “4000000” değerini
üretir.
Hatta YTL fonksiyonuna ToString() methodunuda eklersek
public override string ToString()
{
return this.lira.ToString() + " yeni lira, " + this.kurus.ToString() + " yeni kuruş.";
}
{
return this.lira.ToString() + " yeni lira, " + this.kurus.ToString() + " yeni kuruş.";
}
ve şu satırları çalıştırırsak
YTL i = new YTL(1, 50);
YTL j = new YTL(2, 50);
YTL k = Topla(i, j);
Console.WriteLine(k.ToString());
Console.ReadLine();
YTL j = new YTL(2, 50);
YTL k = Topla(i, j);
Console.WriteLine(k.ToString());
Console.ReadLine();
Ekranda “4 yeni lira, 0 yeni kuruş.” Yazısını görürüz.
Açık ve Gizli Çevrimin Farkı
Burada dikkat edilmesi gereken bir konu tür çevrimi operatörlerinin
önündeki “implicit” işaretidir. Bu fonksiyonları eğer “explicit” işaretleseydik
durum şöyle olurdu.
/// <summary>
/// tl’yi ytl’ye çevirir
/// </summary>
/// <param name="tl"></param>
/// <returns></returns>
static public explicit operator YTL(int tl)
{
if (tl < 0)
throw new ArgumentException("TL sıfırdan küçük olamaz");
YTL ytl = new YTL(0, 0);
ytl.lira = (uint)(tl / 1000000);
ytl.kurus = (ushort)((tl - ytl.lira * 1000000) / 10000);
/// tl’yi ytl’ye çevirir
/// </summary>
/// <param name="tl"></param>
/// <returns></returns>
static public explicit operator YTL(int tl)
{
if (tl < 0)
throw new ArgumentException("TL sıfırdan küçük olamaz");
YTL ytl = new YTL(0, 0);
ytl.lira = (uint)(tl / 1000000);
ytl.kurus = (ushort)((tl - ytl.lira * 1000000) / 10000);
if ((tl - ytl.lira * 1000000 - ytl.kurus * 10000) > 4999)
ytl.kurus++;
ytl.kurus++;
return ytl;
}
}
/// <summary>
/// ytl’yi tl’ye çevirir
/// </summary>
/// <param name="ytl"></param>
/// <returns></returns>
static public explicit operator int(YTL ytl)
{
return (int)(ytl.Lira * 1000000 + ytl.Kurus * 10000);
}
/// ytl’yi tl’ye çevirir
/// </summary>
/// <param name="ytl"></param>
/// <returns></returns>
static public explicit operator int(YTL ytl)
{
return (int)(ytl.Lira * 1000000 + ytl.Kurus * 10000);
}
Ve bu sınıfları kullanırken açık tür çevrimi yapardık.
YTL i = new YTL(1, 50);
YTL j = new YTL(2, 50);
YTL k = (YTL)Topla((int)i, (int)j);
Console.WriteLine(k.ToString());
Console.ReadLine();
YTL j = new YTL(2, 50);
YTL k = (YTL)Topla((int)i, (int)j);
Console.WriteLine(k.ToString());
Console.ReadLine();
İsterseniz tür çevrim operatörlerini ayrı ayrı açık (explicit) ve gizli
(implicit) olarak işaretleyebilirsiniz.
CLR’ın Tip Çevrim Mucizesi ?
Bu kadarı sizi şaşırttı mı ? daha eğlence yeni başlıyor.?Şimdi aşağıdaki
fonksiyonu incelemenizi istiyorum.
static decimal Toplad(decimal a, decimal b)
{
return a + b;
}
{
return a + b;
}
Bu fonksiyon yukarıdaki topla fonksiyonun decimal versiyonu. Şimdi YTL sınıfını
bu fonksiyon ile nasıl kullandığıma bakın.
YTL i = new YTL(1, 50);
YTL j = new YTL(2, 50);
YTL k = Topla(i, j);
YTL p = (int)Toplad(i, j);
Console.WriteLine(k.ToString());
Console.WriteLine(p.ToString());
Console.ReadLine();
YTL j = new YTL(2, 50);
YTL k = Topla(i, j);
YTL p = (int)Toplad(i, j);
Console.WriteLine(k.ToString());
Console.WriteLine(p.ToString());
Console.ReadLine();
Yukarıdaki kodu çalıştırdığımızda ise kod düzgün çalışır ve p 4 ytl 0
kuruş değer üretir. Bizim sınıfımız int’e gizli , int’ de decimal ’a gizli
çevrilebildiği için “Toplad” fonksiyonunu ytl ile kullandığımız zaman JIT ytl yi
önce int’e sonra da decimal’a çevirebiliyor. Fonksiyon decimal sonuç üretince ,
decimal int’e açıktan çevrilebildiği için, bizim sadece sonucu int’e açıktan
çevirmemiz yeterli oluyor, çünkü biz int’i gizli olarak ytl’ye çevirebiliyoruz.
Özetlemek gerekirse özellikle eski kütüphanelerini yeni tipler ile
kullanmak isteyen arkadaşlar eğer tür çevrimini iyi kullanabilirlerse bir çok
zahmetten kurtulurlar. Bitirmeden önce dikkatinizi çekmek istedğim iki konu
var.
1. “YTL” “int” sınıfından türemiyor. Yani alt üst sınıf ilişkisi yok.
2. int’ten yani eski liradan yeniye geçişdeki değer kaybı. Sonuçta kanun ile belirlenen bir değer kaybı olduğu için sorun yaratmaz ancak, siz başka sınıflar arasında tür çevrimleri yaparken bu değer kaybını göz önünde bulundurmayı unutmayın.
2. int’ten yani eski liradan yeniye geçişdeki değer kaybı. Sonuçta kanun ile belirlenen bir değer kaybı olduğu için sorun yaratmaz ancak, siz başka sınıflar arasında tür çevrimleri yaparken bu değer kaybını göz önünde bulundurmayı unutmayın.
Hiç yorum yok:
Yorum Gönder