C# daTipler Arası Nasıl Dönünüşüm Yapılır?
Bir değişken tanımlandığında, o değişkenin türü ve bu türe bağlı olarak bellekte ayrılacak yer de belirlenir.Bu nedenle o değişkene farklı türde değer atanması hataya neden olur.Farklı türdeki değişkenler arasında işlem yapacaksak, değişken dönüşüm işlemi yapmamız gerekir.Değişkenleri dönüştürmek için hazır metotları kullanırız.
Bir değişken tanımlandığında, o değişkenin türü ve bu türe bağlı olarak bellekte ayrılacak yer de belirlenir. Bu nedenle o değişkene farklı türde değer atanması hataya neden olur.
Farklı türdeki değişkenler arasında işlem yapacaksak, değişken dönüşüm işlemi yapmamız gerekir. Değişkenleri dönüştürmek için hazır metotları kullanırız.
Mesela TextBox, Label ve benzeri bütün kontrollerin Text özellikleri string türünde kabul edilir. TextBox içindeki değeri sayısal bir değişkene direkt olarak atayamayız. Çünkü değişkenin türü ile atanmaya çalışan verinin türü farklıdır.
Aynı şekilde sayısal bir değişkeni Label içine direk yazdıramayız. Böyle durumlarda değişken dönüşümü yapmamız gerekir.
Değişken dönüşümü işlemlerini ikiye ayırabiliriz: Açık ve kapalı dönüşüm.
1- Kapalı Dönüşüm:
Küçük tipteki sayısal değişkenlerin değerini, daha büyük tipteki değişkenlere verirken sorun çıkmayacaktır. Burada dönüşüm işlemini program kendisi yapacaktır. Örneğin byte türündeki bir değişkenin sakladığı değer, int tipindeki bir değişkene verilebilir. Çünkü int tipi daha büyük bir veri tipi olduğundan, byte tipindeki veriyi de saklayabilecektir.
Short a = 245;
int b;
b = a;
Bu örnek sorunsuz çalışır çünkü a değişkeninin türü short, b değişkeninin türünden daha küçüktür.
Float a;
İnt b;
a=b;
Bu örnek de sorunsuz çalışır, çünkü float tipi int tipine göre daha büyük sayıları saklayabilecektir.
Ancak aşağıdaki gibi bir kullanım hataya neden olur. Çünkü short türündeki bir değişkene, int tipinde yani daha büyük bir değişkenin değeri verilmeye çalışılmıştır.
Int a=245;
Short b;
b = a;
Aşağıdaki örnekte farklı tiplerde değişkenler tanımlanmış ve birbirlerine dönüştürülmek istenmiştir. Hangilerinin çalışıp, hangilerinin çalışmayacağı da belirtilmiştir.
byte a;
short b;
int c;
long d;
float x;
a=b; (Hata)
b=a; (Çalışır)
c=b; (Çalışır)
c=d; (Hata)
d=c; (Çalışır)
d=x; (Hata)
x=d; (Çalışır)
2- Açık Dönüşüm:
Bu yöntemde dönüşüm işlemini bizim gerçekleştirmemiz gerekmektedir. Bunun için de yerine göre farklı yöntemler kullanılmaktadır.
Mesela Label ve textBox gibi kontrollerin değerleri (Text özellikleri) her zaman string kabul edilir. Dolayısıyla bu kontrollere değer verilirken ya da bu kontrollerden değer alınırken dönüşüm işlemi yapmak gerekir.
a- Convert metodu:
int a;
a= Convert.toInt32(TextBox1.Text);
Bu örnekte metin kutusundaki değeri, integere çevrilerek a değişkenine aldık.
int ort=53;
Label1.Text=Convert.toString(ort);
Bu örnekte ise ort değişkenindeki değeri stringe çevirerek label1 içerisine yazdık.
b- Parse metodu:
String türündeki değerleri sayı türündeki değerlere çevirmekte kullanılır. Mesela bir form elemanındaki değeri bir değişkene alırken kullanılabilecek yöntemlerden biri de budur.
Metni sayıya dönüştürmekten kastımız, rakamlardan oluşan bir metinsel veriyi, sayısal bir veriye çevirmektir. Yani dönüştürülmeye çalışılan metnin içinde rakam haricinde karakterler varsa hata oluşacaktır.
int a;
a= int.Parse(textBox1.Text);
long b = long.Parse(textBox2.Text);
c- toString() metodu:
Sayı ya da farklı tipteki değişkenleri, string tipine çevirebilen bir metottur. Bu yöntemle sadece string tipine dönüşüm yapılabilir.
int b = 100;
label6.Text = b.ToString();
b değişkenini string tipine çevirdik ve label'e yazdık.
label7.Text = comboBox1.SelectedItem.ToString();
combobox kontrolünün seçili elemanını string tipine çevirdik ve label'e yazdık.
d- Cast işlemi:
Bazı durumlarda bu yöntem kullanılabilmektedir. Örneğin object tipindeki değişken veya elemanları diğer tiplere çevirebilir. Aynı zamanda double tipini int tipine çevirebilir, yani sayılar arasında dönüşüm yapabilir. Ama bir string tipini, int tipine ya da int tipini string tipine çeviremez.
Double sayi = 6.789;
int a;
a = (int)sayi;
Bu örnekte double tipindeki sayi değişkenini, int tipine çevirdik.
Label8.Text = (string)ComboBox1.SelectedItem;
Bu örnekte combobox kontrolünün seçili elemanını stringe çevirdik. Yani object tipini, string tipine çevirmiş olduk.
Bilinçsiz tür dönüşümü
Aslında bunu önceki derste görmüştük. Bu derste sadece adını koyuyoruz ve tanımlıyoruz: C#'ta düşük kapasiteli bir değişken, sabit ya da değişken ve sabitlerden oluşan matematiksel ifade daha yüksek kapasiteli bir değişkene atanabilir. Buna bilinçsiz tür dönüşümü denir, bunun için herhangi bir özel kod gerekmez.
using System; class TurDonusumu { static void Main() { byte a=5; short b=10; sbyte c=30; int d=a+b+c; string e="deneme"; char f='k'; object g=e+f+d; long h=d; float i=h; double j=i; double k=12.5f; Console.WriteLine(j+k); } }
Bilinçsiz tür dönüşümüyle ilgili ilginç bir durum söz konusudur. char
türünü kendisinden daha kapasiteli bir sayısal türe bilinçsiz olarak dönüştürebiliriz. Bu durumda ilgili karakterin Unicode karşılığı ilgili sayısal değişkene atanacaktır.
using System; class TurDonusumu { static void Main() { char a='h'; int b=a; Console.WriteLine(b); } }
Bilinçsiz tür dönüşümüyle ilgili diğer ilginç bir nokta ise byte
, sbyte
, short
ve ushort
türündeki değişkenlerle yapılan matematiksel işlemlerdir. Bu tür durumda oluşan matematiksel ifade intleşir. Yani aşağıdaki durumda programımız hata verir:
using System; class TurDonusumu { static void Main() { byte a=5, b=10; short d=2, e=9; byte f=a+b; short g=d+e; Console.WriteLine(f+g); } }
Çünkü artık 8. satırdaki a+b ifadesi intleşmiş, ayrıca da 9. satırdaki d+e ifadesi de intleşmiştir, ve bunları en az int türdeki bir değişkene atayabiliriz. Size yardımcı olması açısında bilinçsiz tür dönüşümü yapılacabilecekler tablosu aşağıda verilmiştir:
Kaynak | Hedef |
---|---|
sbyte | short, int, float, long, double, decimal |
byte | short, ushort, int, uint, long, ulong, float, double, decimal |
short | int, long, float, double, decimal |
ushort | int, uint, long, ulong, float, double, decimal |
int | long, float, double, decimal |
uint | long, ulong, float, double, decimal |
long, ulong | float, double, decimal |
char | ushort, int, uint, long, ulong, float, double, decimal |
float | double |
Bilinçli tür dönüşümü
Bilinçli tür dönüşümü genellikle derleyicinin izin vermediği durumlarda kullanılır. Bilinçli tür dönüşümüyle küçük türün büyük türe dönüştürülmesi sağlanabilse de aslında bu gereksizdir, çünkü aynı şeyi bilinçsiz tür dönüşümüyle de yapabilirdik. Aşağıdaki programda bilinçli tür dönüşümü gerçekleştirilmektedir.
using System; class TurDonusumu { static void Main() { int a=5; byte b=(byte)a; Console.WriteLine(b); } }
Programımızda da görebileceğiniz gibi (byte)a
ifadesi, a değişkeninin byte hâlini tuttu. Aşağıdaki şekil bilinçli tür dönüşümünü anlatmaktadır.
- Eğer değişken adı kısmında tek bir değişken yoksa, bir ifade varsa parantez içine alınması gerekir.
- Bu şekilde tür dönüşümü değişkenlere uygulanabildiği gibi sabitlere de uygulanabilir:
using System; class TurDonusumu { static void Main() { byte b=(byte)12.5f; Console.WriteLine(b); } }
- Reel türler tam sayı türlere dönüşürken ondalık kısım atılır.
- Bilinçsiz tür dönüşümüyle yalnızca küçük türler büyük türlere dönüşebiliyordu, yani veri kaybı olması imkansızdı. Halbuki bilinçli tür dönüşümünde veri kaybı gerçekleşebilir, eğer dönüşümünü yaptığımız değişkenin tuttuğu değer dönüştürülecek türün kapasitesinden büyükse veri kaybı gerçekleşir. Bu gibi durumlar için C#'ın
checked
veunchecked
adlı iki anahtar sözcüğü vardır.
checked
Kullanımı aşağıdaki gibidir:
using System; class TurDonusumu { static void Main() { int i=256; byte b; checked { b=(byte)i; } Console.WriteLine(b); } }
i, byte'a çevrilirken veri kaybı gerçekleştiği için programımız çalışma zamanında hata verecektir. Ayrıca yeri gelmişken bir konuya değinmek istiyorum. Bu programımızda b değişkeni checked
bloklarının içinde tanımlansaydı checked
bloklarının dışında bu b değişkenine erişemezdik, çünkü değişkenler yalnızca tanımlandıkları en iç bloğun içinde aktiftirler. Buradaki "en iç" sözüne dikkat etmenizi öneririm.
{ int b; { int a; } }
Burada a değişkeni yalnızca en iç blokta aktif olmasına karşın, b değişkeni hem dıştaki hem içteki blokta aktiftir.
{ { int a=0; } { int b=0; } Console.WriteLine(a+b); }
Burada her iki değişken de WriteLine
satırının olduğu yerde geçersiz olduğu için bu kod da geçersizdir. Çünkü her iki değişken de tanımlandıkları en iç bloğun dışında kullanılmaya çalışılıyor.
unchecked
Eğer programımızda veri kaybı olduğunda programın hata vermesini istemediğimiz kısımlar varsa ve bu kısımlar checked
bloklarıyla çevrilmişse unchecked
bloklarını kullanırız. unchecked
, checked
'ın etkisini bloklarının içeriği çerçevesinde kırar. Programımızın varsayılan durumu unchecked
olduğu için, yalnızca eğer programımızda checked
edilmiş bir kısım var ve bu kısım unchecked
etmek istediğimiz alanı kapsıyorsa gereklidir, diğer durumlarda gereksizdir. Örnek:
using System; class TurDonusumu { static void Main() { int i=256; int a=300; byte b, c; checked { b=(byte)i; unchecked { c=(byte)a; } } Console.WriteLine(b); } }
Programımız çalışma zamanında hata verir, ancak bunun sebebi c=(byte)a;
satırı değil, b=(byte)i;
satırıdır.
object türüyle ilgili kurallar
C#'taki en ilginç türün object
olduğunu geçen derste söylemiştik, işte bu ilginç türün daha başka kuralları:
- object türündeki bir değişkene başka herhangi bir türdeki değişken ya da sabit (string dışında) + işaretiyle eklenemez. Örneğin aşağıdaki gibi bir durum hatalıdır:
using System; class TurDonusumu { static void Main() { object a='5'; int b=4; Console.WriteLine(a+b); } }
- object türündeki bir değişkene herhangi bir türdeki değişken ya da sabit atanabilir (bilinçsiz tür dönüşümü). Ancak object türündeki herhangi bir değişkeni başka bir türe çevirmek için tür dönüştürme işlemi kullanılır. Ayrıca da dönüştürülen türlerin uyumlu olması gerekir. Yani object türüne nasıl değer atandığı önemlidir. Örneğin aşağıdaki gibi bir durum hatalıdır:
using System; class TurDonusumu { static void Main() { object a="5"; int b=(int)a; Console.WriteLine(b); } }
Ancak aşağıdaki gibi bir kullanım doğrudur.
using System; class TurDonusumu { static void Main() { object a='k'; char b=(char)a; Console.WriteLine(b); } }
Aynı satırda çifte dönüşüm yapılamaz. Aşağıdaki gibi bir kullanım hatalıdır.
using System; class TurDonusumu { static void Main() { object a='c'; int b=(int)a; Console.WriteLine(b); } }
Burada önce objectin chara, sonra da charın inte dönüşümü ayrı ayrı yapılmalıydı. Aşağıdaki gibi bir kullanım hatalıdır:
using System; class TurDonusumu { static void Main() { object a=5; byte b=(byte)a; Console.WriteLine(b); } }
Çünkü derleyici harfsiz tam sayı sayıları int sayar, dolayısıyla da burada uygunsuz bir tür dönüşümünden bahsedebiliriz. Yani 7. satırda a inte dönüştürülmeliydi. Ancak aşağıdaki gibi bir kullanım doğrudur:
using System; class TurDonusumu { static void Main() { byte m=5; object a=m; byte b=(byte)a; Console.WriteLine(b); } }
Bu program hata vermez. Çünkü derleyici a'nın gizli türünün byte olduğunu biliyor.
string türüyle ilgili dönüşümler
Dikkat ettiyseniz şimdilik sadece sayısal türleri, char ve object (uygun şekilde değer verilmiş olması şartıyla) türünü kendi aralarında dönüştürebiliyoruz. Şimdi göreceğimiz metotlarla string türünü bu türlere ve bu türleri de string türüne dönüştürebileceğiz.
x.ToString()
Bu metot x değişken ya da sabitini stringe çevirip tutar. Örnekler:
using System; class TurDonusumu { static void Main() { string b=3.ToString(); Console.WriteLine(b); } }
veya
using System; class TurDonusumu { static void Main() { int a=6; string b=a.ToString(); Console.WriteLine(b); } }
veya
using System; class TurDonusumu { static void Main() { string b=12.5f.ToString(); Console.WriteLine(b); } }
veya
using System; class TurDonusumu { static void Main() { string b='k'.ToString(); Console.WriteLine(b); } }
ToString()
metodu System
isim alanında olduğu için programımızın en başında using System;
satırının bulunması bu metodu kullanabilmemiz için yeterlidir. string türüyle ilgili bilmeniz gereken bir şey daha var:
using System; class TurDonusumu { static void Main() { string b=5+"deneme"+'k'+12.5f; Console.WriteLine(b); } }
Böyle bir kod mümkündür. Ayrıca şöyle bir kod da mümkündür:
using System; class TurDonusumu { static void Main() { int a=5; char m='k'; string r="deneme"; float f=12.5f; string b=a+m+r+f; Console.WriteLine(b); } }
Burada dikkat etmemiz gereken şey yan yana gelen sayısal ve char değer ve değişkenlerle matematiksel toplama yapılmasına rağmen bunların yan yana gelmemesi durumunda da normal yan yana yazma olayının gerçekleşmesidir. Ancak tabii ki şöyle bir durum hatalıdır:
using System; class TurDonusumu { static void Main() { int a=5; char m='k'; float f=12.5f; string b=a+m+f; Console.WriteLine(b); } }
Yani bir sabit ve/veya değişken grubunun bir stringe atanabilmesi için ifadenin içinde en az bir string olmalıdır.
System.Convert sınıfı ile tür dönüşümü
System
isim alanının altındaki Convert
sınıfı içinde tür dönüşümü yapabileceğimiz birçok metot bulunur. Bu metotlarla hemen hemen her türü her türe dönüştürebiliriz. Ancak bunun için değişken türlerinin CTS karşılıklarını bilmeliyiz. Değişken türleri ve CTS karşılıkları aşağıdaki tabloda listelenmiştir.
Tür | CTS karşılığı |
---|---|
bool | Boolean |
byte | Byte |
sbyte | Sbyte |
short | Int16 |
ushort | UInt16 |
int | Int32 |
uint | UInt32 |
long | Int64 |
ulong | UInt64 |
float | Single |
double | Double |
decimal | Decimal |
char | Char |
Şimdi sıra geldi bu metotlara:
- Convert.ToBoolean(x)
- Convert.ToByte(x)
- Convert.ToSbyte(x)
- Convert.ToInt16(x)
- Convert.ToUInt16(x)
- Convert.ToInt32(x)
- Convert.ToUInt32(x)
- Convert.ToInt64(x)
- Convert.ToUInt64(x)
- Convert.ToSingle(x)
- Convert.ToDouble(x)
- Convert.ToDecimal(x)
- Convert.ToChar(x)
Bu metotlar x'i söz konusu türe dönüştürüp o türde tutarlar. x bir değişken, sabit ya da ifade olabilir. x, ifade olduğu zaman önce bu ifade mevcut türe göre işlenir, sonra tür dönüşümü gerçekleşir. Kullanımına bir örnek:
using System; class TurDonusumu { static void Main() { string s1, s2; int sayi1, sayi2; int Toplam; Console.Write("Birinci sayıyı girin: "); s1=Console.ReadLine(); Console.Write("İkinci sayıyı girin: "); s2=Console.ReadLine(); sayi1=Convert.ToInt32(s1); sayi2=Convert.ToInt32(s2); Toplam=sayi1+sayi2; Console.Write("Toplam= "+Toplam); } }
KAYNAK: