Professional Documents
Culture Documents
class IlkKod
{
public static void main()
{
Console.WriteLine("Bir Sonraki Yazida Gorusmek Uzere");
}
}
Boran 1
C DEĞİŞKEN VE METHOD TANIMLARI (2)
DEĞİŞKEN TANIMLAMA
-Aşağıdaki satırda integer tipte bir değişken tanımlanıyor ve değişkenin adı belirtiliyor.
-İkinci satırda ise tip ve değişkenin ardından initializasyon işlemi gerçekleştiriliyor.
Burada bir hatırlatma C#' ta büyük küçük harf ayrımı vardır. Yani;
string ad; ile string Ad; farklı değişkenlerdir.
Ayrıca her satırdan sonra (Method ve Koşul tanımlanan satırlar hariç) noktalı virgül
konulmalıdır.
Şimdide bazı değişken tiplerinin özelliklerine bir bakalım.
METHOD TANIMLAMA
class IlkKod
{
public static void main()
{
Console.WriteLine("Bir Sonraki Yazida Gorusmek Uzere");
}
}
Boran 2
public static void main() satırına bakacak olursak.
Burada bir method tanımlama söz konusu. Yanlız bu main() isimli özel bir method. Tıpkı
C ve JAVA' da olduğu gibi.
Biraz açıklayacak olursak eğer her hangi bir uygulamada main() isimli bir method varsa
ilk önce o icra edilir. Yani
uygulama ilk önce bu method içindeki işlemleri yaparak çalışmaya başlar.
class Test
{
public static void main()
{
Console.WriteLine("Bir Sonraki Yazida Gorusmek Uzere");
}
public void EkranaBas()
{
Console.WriteLine("Bu Mesajı Göremiyeceksiniz.")
}
}
Bu yeni kodumuzda ise, Test isimli class' ımıza EkranaBas() isimli yeni bir method
ekledik.
Bu method içinde, ekranda göstermesi amacıyla Console.WriteLine özelliğini
kullanarak bir mesaj yazdık.Yanlız
bu mesajın içeriğine dikkat ederseniz mesajın ekrana basılmayacağını görebilirsiniz.
Bunun nedeni methodun
çağırılmaması. Bu kod icra edildiğinde sadece main methodu içinde belirtilen mesaj
ekrana basılacaktır. Şimdi
Yukarıdaki kodu biraz daha genişletelim.
class Test
{
public static void main()
{
Console.WriteLine("Bir Sonraki Yazida Gorusmek Uzere");
Test baglan = new Test();
baglan.EkranaBas();
}
public void EkranaBas()
{
Console.WriteLine("Mesajı Artık Görebilirsiniz.")
}
private void Deneme()
{
Console.WriteLine("AspNedir.com")
}
}
Evet new keyword'u aracılığı ile Test class'ına ait bir baglan nesnesi oluşturduk ve
EkranaBas() methodunu çağırdık.
Yanlız burada Deneme() isimli bir method daha var. EkranaBas ile Deneme isimli iki
method'a biraz
dikkat edicek olursak tanımlama esnasında farklılıklarının olduğunu görebiliriz.
EkranaBas methodu public
ile başlarken Deneme methodu private ile başlıyor. Aradaki fark:
PUBLIC: public ile başlıyan methodlar dışarıdan (yani başka bir class'ın içinden)
çağırılabilir.
PRIVATE: private ile başlıyan methodlar ise sadece bulunduğu class içinde
çağırılabilir.
Eğer bu iki kavram kafanızı karıştırdıysa çok üzerinde durmayın. Bir sonraki makalede
Boran 3
daha ayrıntılı bir şekilde açıklamaya
çalışacağım.
Şimdi birazda değişkenlerin method lar içinde nasıl kullanıldıklarına ve nasıl sonuçlar
verdiklerine bakalım.
class Test
{
string yer="class değişkeni";
Bu uygulamada yer değişkeni string tipinde olup iki farklı yerde tanımlanarak yine iki
farklı yerde
içeriği ekrana basılmaktadır. Şimdi; method içinde tanımlanan değişken sadece o method
içinde geçerlidir. Yani main methodu
içindeki mesajda ekrana Method Değişkeni yazılacaktır. Ancak EkranaBas() method'unda
ise ekrana Class Değişkeni mesajı
çıkacaktır.Bunun nedeni EkranaBas methodu içinde yer diye bir değişken tanımlı
olmadığı için derleyici bu değişkeni gidip
class'ın altında arıyacaktır.
FONKSİYONLAR (3)
class AspNedir
{
public static void main()
{
AspNedir baglan = new AspNedir();//baglan nesnesi oluşturuluyor.
int donendeger = baglan.Carp();//baglan nesnesi aracılığı ile Carp
Fonksiyonu çağırılıyor.
Console.WriteLine(donendeger);//Sonuç ekrana Basılıyor
}
public int Carp()
{
int sayi1 = 2;
int sayi2 = 7;
int sonuc = sayi1*sayi2;
return sonuc;//sonuc değişkeninin içeriği kendisini çağırana
döndürülüyor.
}
}
Boran 4
İlk fonksiyon örneğimizi bitirdik. Şimdi kodumuzu bir inceleyelim.
Carp() isimli fonksiyon, public ve integer tipte. Yani bu fonksiyon dışarıdan çağırılabilir
ve
kendisini çağıran Method yada Fonksiyona integer tipinde bir değer döndürür. Bu
döndürme işleminide
return ifadesiyle yaparız.
Bu örneğe göre fonksiyonun kısa bir tanımını yapacak olursak.
Fonksiyon: Eğer yazdığımız kod bloğu geriye bir değer döndürüyorsa fonksiyondur.
Döndürmüyor ise fonksiyon
değil Method' dur.
class AspNedir
{
public static void main()
{
AspNedir baglan = new AspNedir();
int donendeger = baglan.Carp(3,7);
Console.WriteLine(donendeger);
}
public int Carp(int sayi1, int sayi2)
{
int sonuc = sayi1*sayi2;
return sonuc;
}
}
Yukarıdaki örnekte görüldüğü gibi dilersek bir Fonksiyona dışarıdan değer gönderip, bu
değerleri
işlemesini sağlıyabiliriz.
ARRAY'LER
class AspNedir
{
public static void main()
{
int[] myArray={1,2,3};
Console.WriteLine(myArray[0]);
Console.WriteLine(myArray[1]);
Console.WriteLine(myArray[2]);
}
}
Yukarıdaki örnekte integer tipte bir dizi tanımlayarak değer atamalarını yaptım.
Aşağıdaki örnekte ise bu sefer iki boyutlu olan yine integer tipte bir array tanımladım ve
For döngüsünü kullanarak dizinin değerlerini atadım.
using System;
Boran 5
baglan.EkranaBas();
}
}
}
Dilersek bir dizinin sınırlarını dinamik olarakta belirliyebiliriz. Tek yapmamız gereken
dizinin
sınırlarının oluşturulduğu fonksiyon tarafından dışarıdan değer olarak almasını
sağlamak.
Boran 6
C# C SHARP A GENEL BAKIS
Boran 7
string MyStr1=”Visual”;
string MyStr2=”Studio”;
string MyStr3=”.net”;
string MyStr4=MyStr1+” “+MyStr2+” “+MyStr3;
MyStr4.ToUpper();
//Sonuç olarak MyStr4’e VISUAL STUDIO .NET değeri atanır.
Boran 8
Daha sonraları COM sayesinde dil uyumluluğu sağlandı ve
programlama dilleri (VB,VJ++,C ve C++) çok basit bir şekilde COM
objesi olarak yazılan classlara ulaşabildiler. Ancak COM öğrenmesi
çok zor bir yapı olması dezavantajını hep taşıdı ve tam anlamıyla
klasik Object Oriented Programlama yolunda inheritence’ı
destekleyemedi.
· Assembly
o C,C++
§ C#,J++
· Visual Basic
Boran 9
Listemizde yukarıdan aşağıya doğru inecek olursak aşağıya indikçe
dillerin öğrenimi kolaylaşır.Daha az kod yazarak ve daha az zaman
harcayarak istediğimiz projeleri gerçekleştirebiliriz. Assembly ile
yazılım geliştiriyorsak hiç alışık olmadığımız bir performansla
karşılaşırız ancak assembly öğrenmesi, yazılım geliştirmesi en zor
platformlardan birisidir. Bu nedenle assembly dili ile yazılmış
programlar genellikle çok yüksek performansın ön planda olması
gereken bazı device driver’lar, oyun subroutine’leri ve işletim
sistemlerinin temel dosyalarıdır (win.com gibi). C++ ise GUI
(Graphical User Interface) geliştirmek için tercih edilmesi gereken
bir dildir. Eğer daha basit bir şekilde GUI’ler geliştirmek istiyorsak
tercihimiz tabiiki Visual Basic olmalıdır. GUI’lerde performans ön
planda değildir çünkü burada limit faktörü kullanıcıdadır yani
kullanıcının mouse’ı hızlı tıklamasındadır!..
C#’ın C++ ve Visual Basic arasında bir dil olduğuna iyi bir örnek
olarak memory management gösterilebilir. Visual Basic’deki tek
memory management şudur: nesnelerle işiniz bittiğinde set
nesne=nothing demeniz yeterlidir, bunu yapmayı unutursanız
olacak tek kötü şey sistem kaynakları ve memory’nin
gerektiğinden biraz daha uzun bir süre kullanılması olacaktır.
Boran 10
Şu ana kadar bahsettiklerimizi değerlendirecek olursak
Microsoft’un .NET platformuna uygun olarak ürettiği C#’a Visual
Basic yada C++ dilleri ile uygulama geliştiren developerların aynı
çatı altında toplanacağı bir yapı olarak bakabiliriz. Daha az zaman
harcayarak, daha az kod yazarak daha güçlü applikasyonlar
geliştirmek için C# mükemmel bir platform gibi gözüküyor. C# ile
tanışmak ve çalışmak gerçekten heyecan verici. İyi ki doğdun C#.
// Basit Tanımlama
int i;
// Bileşik tanımlama
int i,j,k;
Boran 11
using System;
public class ForcedInit
{
public static int Main()
{
int k;
Console.WriteLine(k);
return 0;
}
}
using System;
public class ForcedInit
{
public static int Main()
{
int k=0; //k değişkeni tanımlandı ve initialize edildi
Console.WriteLine(k);
return 0;
}
}
Bu kodu compile ettiğimizde ise herhangi bir hata ile karşılaşmayız çünkü k
değişkeni tanımlanmış ve aynı zamanda initializasyona işleminden geçmiştir yani bir
başlagıç değeri almıştır.
using System;
public class ReferenceType
{
public int MyData;
}
public class SimpleClass
{
public static int Main()
{
ReferenceType objA;
Boran 12
//new keyword'ü kullanılarak ReferenceType
instantiate ediliyor
objA=new ReferenceType();
objA.MyData=5;
return 0;
}
}
using System;
public class ReferenceType
{
public int MyData;
}
public class SimpleClass
{
public static int Main()
{
ReferenceType objA;
ReferenceType objB;
ReferenceType objC;
objA=new ReferenceType();
objA.MyData=5;
//Aşağıdaki kod ile objA'nın aynı instance referansını
//objB ve objC'ninde almasını sağlarız.
objB=objA;
objC=objA;
return 0;
}
}
using System;
public class ReferenceType
{
public int MyData;
}
public class SimpleClass
{
public static int Main()
{
ReferenceType objA;
Boran 13
//new keyword'ü kullanılarak ReferenceType
instantiate ediliyor
objA=new ReferenceType();
objA=null;
return 0;
}
}
Program buglarını ortadan kaldırmak için (bug-free programs) C# çok güçlü typed
bir dildir. Değişkenler arasındaki dönüşümler sadece ihtiyaç duyulduklarında
kullanılmalıdır. Örnek verecek olursak bool tanımlı bir değişkeni string değişken tipindeki
bir değere dönüştürmek için bunu belirtmeniz gerekmektedir. Bu sayede program
otomatik olarak değişken tiplerini convert etmekle uğraşmayacaktır, bu da programın
daha hızlı çalışmasını sağlayacaktır.
using System;
public class Donusum
{
public static int Main()
{
bool MyBool=true;
string i,j;
i=MyBool;
MyBool=false;
j=MyBool;
Console.WriteLine(i);
Console.WriteLine(j);
Console.ReadLine();
return 0;
}
}
Yukarıdaki kodu compile ettiğimizde bir hata ile karşılarız: “Cannot implicitly
convert type ‘bool’ to ‘string’ ”.
Boran 14
Programın düzgün olarak çalışabilmesi için bool değişken tipinin .ToString()
metodu kullanılarak ilgili çevrimin belirtilmesi gerekmektedir.
using System;
public class Donusum
{
public static int Main()
{
bool MyBool;
string i,j;
MyBool=true;
i=MyBool.ToString();
MyBool=false;
j=MyBool.ToString();
Console.WriteLine(i);
Console.WriteLine(j);
Console.ReadLine();
return 0;
}
}
Boxing ve Unboxing
using System;
public class BoxingExample
{
public static int Main()
{
object objA;
int i,j;
Boran 15
//Bu işlem ise referans değerini stack'de tutulan
//bir value değerine atar (unboxing)
j=(int)objA;
Console.WriteLine(j);
Console.ReadLine();
return 0;
}
}
using System;
public class BoxingExample
{
public static int Main()
{
int i=10;
object objA;
byte j;
objA=(object)i;
j=(byte)objA;
Console.WriteLine(j);
Console.ReadLine();
return 0;
}
}
Array’ler
using System;
public class ArrayExample
{
public static int Main()
{
//Aşağıdaki işlem array tanımını ve
//değer atamasını gerçekleştirir.
int[] aryInt={1,2,3};
Boran 16
return 0;
}
}
using System;
public class ArrayExample
{
public static int Main()
{
//Aşağıdaki işlem 2D bir array tanımını ve
//değer atamasını gerçekleştirir.
int[,] aryInt=
{
{1,2,3},
{4,5,6},
{7,8,9}
};
return 0;
}
}
Alternatif olarak new keyword’ü ile dimension’ı daha sonra belirtilmek üzere bir
array tanımlanabilir.
using System;
public class Arrays
{
private int MaxCols;
private int MaxRows;
private bool[,] MyBool;
public Arrays(int Rows, int Cols)
{
MaxCols=Cols;
MaxRows=Rows;
MyBool=new bool[Rows,Cols];
}
}
public class ArrayExample
{
public static int Main()
{
Boran 17
Arrays MyArray=new Arrays(1,2);
return 0;
}
}
C# aynı zaman ‘orthogonal’ (dikey) ve ‘jagged’ (çapraz – her rowda farklı eleman
sayısına sahip diziler) array tanımlamalarına izin verir. Aşağıdaki örnek 1.rowunda 1,
2.rowunda 2, 3. rowunda 3 elemana sahip bir ‘diagonal matris’ (yatay) tanımı yapacaktır.
using System;
public class ArrayExample
{
public static int Main()
{
int[][] ary=new int[3][];
ary[0]=new int[1];
ary[1]=new int[2];
ary[2]=new int[3];
ary[0][0]=1;
ary[1][0]=2;
ary[1][1]=3;
ary[2][0]=4;
ary[2][1]=5;
ary[2][2]=6;
for (int i=0;i<=2;i++)
{
for (int j=0;j<=i;j++)
{
Console.Write(ary[i][j].ToString()+" ");
}
Console.WriteLine();
}
Console.ReadLine();
return 0;
}
}
using System;
public class ArrayExample
{
public static int Main()
{
int[] ary={7,3,9};
//Aşağıdaki kod tanım sırası ile değerleri
Boran 18
//ekrana yazdırır
foreach (int j in ary)
{
Console.Write(j.ToString()+" ");
}
Console.WriteLine();
//Aşağıdaki kod Matris'i ters çevirir
Array.Reverse(ary);
foreach (int j in ary)
{
Console.Write(j.ToString()+" ");
}
Console.WriteLine();
//Aşağıdaki kod ise dizi elemanlarını sıralar
Array.Sort(ary);
foreach (int j in ary)
{
Console.Write(j.ToString()+" ");
}
Console.ReadLine();
return 0;
}
}
Enumeration
using System;
public class EnumerationExample
{
enum Renkler {Siyah,Beyaz,Kirmizi,Mavi};
public static int Main()
{
Renkler[]
j={Renkler.Beyaz,Renkler.Kirmizi,Renkler.Mavi,Renkler.
Siyah};
for (int i=0;i<4;i++)
{
Console.WriteLine(j[i]);
}
Console.ReadLine();
Boran 19
return 0;
}
}
Constant
Data tipleri hakkında birçok noktaya değindikten sonra şimdi de akış kontrol
mekanizmalarına göz atabiliriz.
Fonksiyonlar
· Yeniden kullanım,
Fonksiyon Tanımlama
Bir fonksiyon matematikte olduğu gibi geriye her zaman bir değer döndürür. Bu
tanımdan yola çıkarak tanımlayacağımız fonksiyonun ne tip değer döndüreceğini de
söylememiz gerekmektedir. Aynı zamanda fonksiyonlar’ın içerisine yine tipi belli değerler
parametere olarak gönderilebilir. Geriye döndürdüğümüz değeri ise return statement’ı ile
compiler’a belirtiriz. Eğer geriye bir parameter göndermek istemiyorsak o zaman
kullanmış olduğumuz yapı fonksiyon değil bir metoddur.
Bir class içerisinde tanımlı bir fonksiyonu class içerisinden instance’ını yaratmadan
kullanabilmek için static keyword’ünü kullanırız.
Boran 20
ReturnValue=value1;
}
else
{
ReturnValue=value2;
}
return ReturnValue;
}
using System;
public class FunctionExample
{
public static int Max(int value1, int value2)
{
int ReturnValue;
if (value1>value2)
{
ReturnValue=value1;
}
else
{
ReturnValue=value2;
}
return ReturnValue;
}
public static int Main()
{
int k;
k=Max(1,5);
Console.WriteLine(k);
Console.ReadLine();
return 0;
}
}
Fonksiyonlar ve Parametreler
C#’ta fonksiyon kullanımı sırasında value tipler value referans tipler ise referans
olarak fonksiyon içerisine geçer. Bu pratik olarak şu demektir fonksiyonun içerisine
gönderilen değer parametrenin bir kopyasıdır ve değer üzerinde yapılan herhangi bir
değişiklik parametrede bir değişikliğe yol açmaz. Bunu bir örnekle açıklamak yerinde
olacaktır.
Boran 21
using System;
public class ByValSample
{
//void deyimi ile geriye parametre döndürmeyeceğimiz
//yani kullanılan fonksiyonun bir metod gibi davranacağını
//belirtiyoruz.
public static void ChangeValue(int y)
{
y=20;
return;
}
public static int Main()
{
int x=10;
ChangeValue(x);
Console.WriteLine("Metod Çağrıldıktan Sonra x="+x);
Console.ReadLine();
return 0;
}
}
using System;
public class RefSample
{
//ref keyword'ü ile parametrenin referans olarak
//işlem göreceğini belirtiyoruz.
public static void ChangeValue(ref int y)
{
y=20;
return;
}
public static int Main()
{
int x=10;
Console.WriteLine("Metod çağrılmadan önce x="+x);
Boran 22
//İçeriye gönderilen parametrenin referans olarak
//geçmesini sağlıyoruz.
ChangeValue(ref x);
Console.ReadLine();
return 0;
}
}
using System;
public class OutSample
{
public static void ChangeValue(out int y)
{
y=20;
return;
}
public static int Main()
{
int x;
ChangeValue(out x);
Console.ReadLine();
return 0;
}
}
using System;
public class ParamExample
{
Boran 23
public static int FindMinimum(params int[] values)
{
int intMin=-1;
//.Length ile fonksiyona herhangi bir
//parametre gönderilip gönderilmediğini anlıyoruz.
if (values.Length>0)
{
intMin=values[0];
}
for (int i=1;i<values.Length;i++)
{
if (values[i]<intMin)
{
intMin=values[i];
}
}
return intMin;
}
public static int Main()
{
int j,k;
//j değişkenine 2 değerden küçük olanı atanıyor.
j=FindMinimum(5,4);
Console.WriteLine(j);
Console.WriteLine(k);
Console.ReadLine();
return 0;
}
}
Boran 24
Namespace, Value ve Referans Type'ların Kullanımı
Namespaces
namespace Netron.Otomasyon.OtomasyonClasses
{
//class tanımlamaları
}
using Netron.Otomasyon.OtomasyonClasses;
using keyword’ü ile ilgili ilginç bir şey ise onu alias type
tanımlamak için kullanabilmemiz. Aşağıdaki örnek System.Int32
type’ını MyInteger adıyla kullanmamızı sağlar.
using MyInteger=System.Int32;
public class AliasOrnek
{
public static MyInteger Main()
{
MyInteger i=1;
MyInteger j=i+1;
System.Console.WriteLine(j);
return 0;
}
}
Boran 25
System Namespace
Value tipler stackte tutulur, her iki value değeri için yapılmış
atama işlemi ile hafızada birbirinin kopyası iki bölüm oluşturulur.
Referans tipler ise heap’de tutulur. Her iki referans değeri için
yapılmış atama işlemi ile memory’deki tek bir yere iki ayrı referans
oluşturulur.
using System;
public class Simpleclass
{
public static int Main()
{
int i;
int j;
i=5;
j=i;
Console.WriteLine("i="+i);
Console.WriteLine("j="+j);
unsafe
{
if (&i==&j)
Boran 26
{
Console.WriteLine("i ve j'nin adresleri aynı");
}
else
{
Console.WriteLine("i ve j'nin adresleri farklı");
}
}
Console.ReadLine();
return 0;
}
}
using System;
public class ReferenceType
{
public int MyValue;
}
public class SimpleClass
{
public static int Main()
{
ReferenceType i;
ReferenceType j;
i=new ReferenceType();
i.MyValue=5;
j=i;
Console.WriteLine("i.MyValue="+i.MyValue);
Console.WriteLine("j.MyValue="+j.MyValue);
unsafe
{
if (i==j)
{
Console.WriteLine("i ve j aynı adreste");
}
else
{
Console.WriteLine("i ve j farklı adreste");
}
}
Console.ReadLine();
return 0;
}
}
Boran 27
Primitives olarak adlandırılan pek çok değişken tipi C#’da
value tipi olarak kabul edilir : integer value tipi gibi. Aynı zamanda
struct ile tanımlamanan user tipler’de value tipinde
tanımlamalardır.
Instance Constructrolar
int[] MyIntArray={1,2,3,4};
Boran 28
okunmadan önce doğru değere atanma yapılmasını garanti etmiş
olur.
using System;
class Tarih
class Class1
Boran 29
[STAThread]
Console.WriteLine("Yıl:{0}",a.Yil);
Console.WriteLine("Ay:{0}",a.Ay);
Console.WriteLine("gün:{0}",a.Gun);
Console.ReadLine();
using System;
class Tarih
public Tarih()
Gun=1;
Ay=1;
Yil=1970;
Boran 30
}
class Class1
[STAThread]
Console.WriteLine("Yıl:{0}",a.Yil);
Console.WriteLine("Ay:{0}",a.Ay);
Console.WriteLine("gün:{0}",a.Gun);
Console.ReadLine();
Boran 31
using System;
class Tarih
public Tarih()
Gun=1;
Ay=1;
Yil=1970;
Gun=Day;
Ay=Month;
Yil=Year;
class Class1
[STAThread]
Boran 32
Console.WriteLine("a.Yıl:{0}",a.Yil);
Console.WriteLine("a.Ay:{0}",a.Ay);
Console.WriteLine("a.Gün:{0}",a.Gun);
Console.WriteLine("b.Yıl:{0}",b.Yil);
Console.WriteLine("b.Ay:{0}",b.Ay);
Console.WriteLine("b.Gün:{0}",b.Gun);
Console.ReadLine();
Görüldüğü gibi a ile ilgili olan tarih 1.1.1970 iken b ile ilgili
olan tarih parametrik olarak ikinci constructor’a yönlendiği için
2.2.2002 tarihini elde etmiş oluruz. Dikkat ettiyseniz birinci
constructor içerisinde de ikincisine benzer bir işlem yaptık; basit
bir assignment işlemi. Her seferinde aynı kodu yazmaktansa diğer
bir yöntem ile işimizi biraz daha kolaylaştırabiliriz birinci
constructor çağrıldığında onu ikinci constructor’a yönlendirebiliriz:
using System;
class Tarih
public Tarih():this(1,1,1970)
Boran 33
Gun=Day;
Ay=Month;
Yil=Year;
class Class1
[STAThread]
Console.WriteLine("a.Yıl:{0}",a.Yil);
Console.WriteLine("a.Ay:{0}",a.Ay);
Console.WriteLine("a.Gün:{0}",a.Gun);
Console.WriteLine("b.Yıl:{0}",b.Yil);
Console.WriteLine("b.Ay:{0}",b.Ay);
Console.WriteLine("b.Gün:{0}",b.Gun);
Console.ReadLine();
Boran 34
noktada bilmemiz gereken bir kural ise bir initializer list içerisinde
tanımlı metod’un kendi kendini çağıramamasıdır.
using System;
class MyArray
MaxRangeOfArray=MaxRange;
Boran 35
public void CreateArray()
MyArr=new int[MaxRangeOfArray];
class Class1
[STAThread]
a.CreateArray();
a.MyArr[1]=2;
Console.ReadLine();
CONSTRUCTORS
using System;
class AspNedir
{
public int number=3;
Boran 36
}
public void setNumber(int
newNumber)
{
number = newNumber;
}
public int getNumber()
{
return number;
}
}
Konumuza direkt örnek bir kod yazarak başladım. İncelersek eğer şimdiye kadar ki makalelerimiz
de
tanımladığımız methodlara hiçte benzemiyen bir method tanımlaması yaptığımızı görebilirsiniz.
AspNedir()
isimli bu methodumuzun iki önemli özelliği var. İlki adının class'ımızın adı ile aynı olması.
Diğeri ise herhangi bir return değerinin olmayışı. Bildiğiniz gibi methodları tanımlarken return
tiplerini de
belirtmek zorundaydık. Method eğer herhangi bir değer döndürmeyecekse return tipini void olarak
belirtiyorduk. Ancak burada sözü geçen methodumuz için bunların hiç birisi geçerli değil.
Class ile aynı adı taşıyan ve herhangi bir return değeri olmayan methodlara Constructor Methodlar
diyoruz.
Herhangi bir class'ı çağırdığımızda ilk önce o class'a ait constructor çalışır. Dolayısıyla, eğer her
hangi bir
işlemin class ilk çağırıldığında yapılmasını istiyorsak bu işlemleri constructor içinde veya constructor
tarafından
tetiklenen başka bir method içinde yapabiliriz.Bu yöntemini genelde class'a ait bir takım
değişkenlerin
değerlerini set etmek için kullanırız.
Console.WriteLine(test.getNumber());
Console.ReadLine();
}
Burada methodun döndüreceği değer 5 olucak. Daha önce belirttiğim gibi her hangi
bir class'ı çağırdığımızda
ilk önce o class'ın Constructor methodu çalıştırılır. Örneğimizde ki constructor' da
number değişkenini set ederek
değerini beş'e eşitliyor.
Yukarıda, herhangi bir class'ı çağırdığımızda ilk önce constructor'ın çalışmaya başladığını
belirttik.
Peki eğer çağırılan class'ın herhangi bir constructor'ı yoksa ne olucak,örneğin daha önce
hazırladığım makalelerde ki
örneklerin hiç birinde constructor methodunu yazmamıştım.
Aslına bakarsanız her class'ın default bir constructor methodu vardır ve boştur. Yani
demin ki örneği baz alırsak;
public AspNedir() // Default
Constructor Methodu
{
}
Constructor'ımıza dışarıdan değer de gönderebiliriz. Şöyle ki;
using System;
Boran 37
class AspNedir
{
public int number;
Console.WriteLine(test.getNumber());
Console.ReadLine();
}
Dilersek aynı class için de birden fazla constructor tanımlıyabiliriz. Yukarıda ki
örneklerde de gördüğünüz gibi
constructor' lar her hangi bir isim ile tanımlanmadıklarından derleyici hangi
constructor'ın çağırıldığını methodun
dışarıdan aldığı parametrelere göre ayırır. Aynı işlem method ve fonksiyonlar için de
geçerlidir.
Buna Overloading denir. Şimdi bu kavramı inceliyelim.
OVERLOAD KAVRAMI
İsimleri aynı ancak dışarıdan aldığı parametrelerin pirimitiv tipleri farklı olan iki ayrı
method yada
fonksiyon tanımlama işlemine Overloading denir. Bir örnek vericek olursak.
using System;
class AspNedir
{
public static void Main()
{
AspNedir test = new AspNedir();
Console.WriteLine(test.TestMethod("İlk Methodu Çağırıyorum"));
Console.WriteLine(test.TestMethod(6));
Console.ReadLine();
}
public String TestMethod(String newMesaj)
{
String mesaj = "String deger alan Methodhodu çağırdınız =" + newMesaj;
return mesaj;
}
public String TestMethod(int sayi)
{
String mesaj = "Integer deger alan Methodhodu çağırdınız =" + sayi;
return mesaj;
}
}
Görüldüğü gibi iki methodun da isimleri ve return tipleri aynı olmasına rağmen dışarıdan
aldığı parametre tipleri
Boran 38
farklı olduğu için istediğimiz methodu yada fonksiyonu çağırabildik. Aynı işlemi yukarıda
anlattığım
constructor'lar için de gerçekleştirebiliriz.
OVERWRITE KAVRAMI
Bazen daha önce programın herhangi bir yerinde tanımlamış olduğumuz bir method yada
değişkeni ezmek isteriz.
Yani aynı tipte ve özelliklerde bir method yada değişken daha yaratarak ilk önce
yaratılanın etkisiz kalmasını
sağlıyabiliriz. Tabi bu bilerek yapılabileceği gibi dikatsizlik sonucu istenmeden de
gerçekleşebilecek bir olay.
Bu makalemizde şimdilik sadece değişkenleri overwrite etme üzerin de duracağız.
using System;
class AspNedir
{
public int deger = 7;
Boran 39
C#' ta IO (Girdi/Çıktı) İŞLEMLERİ
• Directory
• DirectoryInfo
• File
• FileInfo
Boran 40
GetAttributes-SetAttributes GetFiles
GetCreationTime-SetCreationTime GetDirectoryRoot
GetLastAccessTime-SetLastAccessTime GetLogicalDrives
GetLastWriteTime-SetLastWriteTime GetParent
Move GetCreationTime-SetCreationTime
OpenRead GetCurrentDirectory-SetCurrentDirectory
OpenWrite GetFileSystemEntires
- GetLastAccessTime-SetLastAccessTime
- GetLastWriteTime-SetLastWriteTime
using System;
using System.IO;//System.IO namespace'i
namespace AspNedir
{
public class systemIO
{
public static void Main()
{
//DirectoryInfo
DirectoryInfo dir = new DirectoryInfo(@"c:\");
//Belirtilen klasör altındaki dosyalar.
FileInfo[] file = dir.GetFiles();
foreach (FileInfo fileList in file)
{
Console.WriteLine("Dosyalarım={0}",fileList);
}
Console.Read();
//Dosya Belirleniyor.
FileInfo myFile = new FileInfo(@"c:\AspNedir.txt");
//FileStream Kapatılıyor.
myFs.Close();
}
}
}
Boran 41
Son örnekle birlikte kısa bilgiler de verdiğim FileInfo ve DirectoryInfo
Sınıflarına ait methodların içeriğini ve Text Dosyalarını okuyup - yazma
işlemlerine bir
sonraki yazımda devam edicem. Şimdilik bu kadar.
Boran 42
// matrisin köşegeninin üzerindeki değerler
// pozitif - sol üst köşeden sag alt köşeye olan
// uçerli elemanlar oluşturulur
cout << " pozitif değerler
";
i = 0;
k = 0;
do
{
t = 1;
for (j=0; j<=2; j++)
{
cout << " " << i << " " << j << " ";
t = t * a[i][j];
i++;
}
i = i - 2;
b[k] = t;
cout << b[k] << "
";
t = 1;
k = k + 1;
}
while ( i <= 2);
// negatif değerler
// sağ üst köşeden sol alt köşeye üçerli elemanlar
// olusturulur
cout << "
negatif değerler
";
t = 1;
k = 0;
// -
i = 0;
do
{
for (j=2; j>=0; j--)
{
cout << " " << i << " " << j << " ";
t = t * a[i][j];
i++;
}
i = i - 2;
c[k] = t;
cout << c[k] << "
";
t = 1;
k = k + 1;
}
while ( i <= 2);
t = 0;
for (i = 0; i<=2; i++)
{
t = b[i] - c[i];
cout << t << "
";
}
getch();
}
Boran 43
C# ve XML
Bildiğiniz gibi xml çeşitli sistemler arasında ver alış verişi
yapmamızda bize ciddi
kolaylıklar sağlamakta. Hangi teknolojilerle çalıştığımızın çok
önemi yok. Her dilin kendine
göre bu XML File'larını parse etme yöntemi var. Bu makalemde
sizlere C# ve XML ilişkisini
aktarmaya çalışacağım.
XML Dosyaları üzerinde işlem yapmamızı sağlıyan methodlar
System.Xml namespace'i
içinde yer alır.
using System;
using System.Xml;
namespace XMLProject
{
public class XMLClass
{
Boran 44
}
}
Boran 45
XmlElement addBolum = doc.CreateElement("Bolum");
addBolum.InnerText = "Bilgi Islem";
addSicil.AppendChild(addBolum);
doc.DocumentElement.AppendChild(addSicil);
Şimdilik bu kadar. Bundan önceki C# ta Dosya işlemleri isimli iki yazım ile beraber
üç makalelik bir diziyi geride bıraktık. Sanırım bu üç makale Text Dosyaları üzerinde
yapabileceğimiz işlemler konusunda sizlere bir fikir vermiştir. İlerliyen günlerde farklı
konular ile tekrar birlikte olucaz. Makale Önerileriniz, soru ve elştirileriniz için mail
adreslerim;
Boran 46
int maxSayi = 49;
int rndSayi;
bool aa;
Random rnd=new Random();
for ( int i = 1 ; i <= Defa ; i++ )
{
Tekrar:
rndSayi = rnd.Next(1,maxSayi);
aa = isExist(rndSayi);
if(aa)
{
goto Tekrar;
}
else
{
myCheckString = myCheckString + rndSayi.ToString() + ",";
}
}
myCheckString = myCheckString.Substring(0,(myCheckString.Length)-1);
string[] arrCheckString;
arrCheckString = myCheckString.Split(',');
for(int k = 0 ; k <= arrCheckString.Length-1 ; k++)
{
Response.Write (arrCheckString[k] + "<br>");
}
}
private bool isExist(int Sa)
{
if(myCheckString == ""){return false;}
string[] arrCheckString1;
arrCheckString1 = myCheckString.Split(',');
for(int k = 0 ; k <= arrCheckString1.Length-1 ; k++)
{
if(Sa.ToString() == arrCheckString1[k])
{
return true;
}
}
return false;
}
Evet kodumuzu çalıştırdığımızda, butona basaraka 1 ile 49 arasında rastgele üretilmiş 6 tane sayıyı
bize altalta listeleyecektir
Boran 47
Visual C# ile Windows Menuleri Hazırlama
Merhaba. Bu makalemizde, hemen hemen tüm Windows uygulamalarının temel yapıtaşı olan
windows menulerin nasıl hazırlandıgını ve basit bir uygulamasını adım adım göreceğiz. Bildiğiniz
gibi windows menulerini şimdiye kadar Visual Basic ortamında çok basit bir şekilde yapmak
mümkündü. Ama artık Visual C# ile menu hazırlamak hem daha kolay hem de daha eğlenceli. Bu
makalede yapacağımız uygulamadaki amacımız File ve Edit bölümünden oluşan windows menüsünü
tek bir Windows butonuyla aktif yada pasif duruma getirmek.
Şimdi uygulamamızın ilk adımı olan yeni proje oluşturma sayfasını açalım.
File->New -> Project menüsünü kullanarak aşağıdaki gibi yeni bir proje oluşturalım.
Proje tipi olarak Visual C# Project, template olarak da Windows Application seçtikten sonra
projemize uygun isim verip OK butonuna tıklayalım.
Projemizi oluşturduğumuzda Visual C# IDE sinin bizim için bir başlangıç formu oluşturduğunu
görürüz. Bu form doğal olarak şuanda boştur. Toolbox menusunu kullanarak Form üzerine
istediğimiz kontrolleri sürekle bırak yöntemiyle yerleştirebiliriz. Yada istediğimiz kontrolü çift
tıklayarak ta aynı işlevi gerçekleştirebiliriz. Eğer toolbox menusunu göremiyorsanız ekranın sol alt
küşesinde bulunan
ToolBox ikonuna tıklayın. Şimdi formumuza basit bir MainMenu kontrolu ekleyelim. Yine ToolBox
menüsünden aşağıdaki ikona şekline benzeyen kısma cift tıklayın. Eğer işlem başarılıysa
formunuzun en üst kısmında edit edilmek üzere bir menu oluşacaktır.
Boran 48
MainMenu üzerine fare ile gelerek istediğiniz menu elemanlarını ekleyin.Ben önce File elemanını
sonra Edit elemanını ve Edit elemanının içinde de Copy ve Paste menu elemanlarını aşağıdaki gibi
oluşturdum.
Evet. Form tasarım işlemi bitti. Şimdi sıra geldi BizimButon ile menuye aktif ve pasif durumları
arasında geçiş yaptırmak. Tabi asıl işte şimdi başlıyor.
Form üzerindeki butona çift tıklayarak kod yazma ekranına gelelim.
Gördüğünüz gibi Visual C# bizim için bir takım kodlar oluşturdu. Biraz bu hazır kodları anahatlarıyla
inceleyelim.
using System;
using System.Drawing;
using System.Collections;
Boran 49
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
private void InitializeComponent() işlevi ile Form1 sınıfı içindeki elemanlarla ilgili ilk
işlemler yapılıyor. Elemanların form üzerindeki yeri ve elemanlara ait Propertirs penceresinden
tanımladığımız bütün özellikleri bu işlev ile yerine getirilir.
Bu kodu yazabilmek için form design penceresinden BizimButan çift tıklayarak BizimButon_cilick()
işlevinin içine geçelim. Yukarıdaki kodda eğer menuEdit aktifse pasif duruma getiriyoruz ve
BizimButon a da "MENU AKTIF ET" yazıyoruz. Eğer menuEdit zaten pasifse Menuyu aktif hale
getirip BizimButon yazısınıda "MENU PASIF ET" yapıyoruz. Aşağıda her iki durum için programımızın
çıktısı mevcuttur.
Boran 50
Yazar: Sefer Algan
algans@itu.edu.tr
Boran 51
C# ile Dinamik Yaratılan Resimler(System.Drawing)
Bugün özellikle son kullanıcıya sunulacak olan grafiklerin gösteriminde ihtiyaç
duyabileceğiniz bir konu üzerinde duracağım.
Yapacağımız iş şu, dışarıdan aldığımız parametreleri analiz ederek, bu analiz
sonucunu ekrana grafiksel olarak dökmek.
Gerçi aynı işi daha önceden hazırlanmış bir Component kullanarakta gerçekleştire
bilirsiniz. Bu işi kendimiz yapmak istiyorsak başvuracağımız namespace'in adı
System.Drawing ve birlikte gelen bir kaç class olacak. Örneğimizde kullanacağımız
sistem class'ları;
using System.Drawing;
using System.Drawing.Imaging;
Örneğimizde bir ilçede yaşayan insanların okuma-yazma durumlarına
ilişkin bilgiler
dışarıdan parametre olarak veriliyor. Program bu girilen bilgileri küçük bir
analiz
aşamasından geçirdikten sonra sonuçlarını grafiksel olarak ekrana basıyor.
Şimdi dilerseniz grafiği çizecek olan dosya üzerinde ki kodları inceleyelim.
namespace AspNedir
{
public class BarChart : System.Web.UI.Page
{
private void Page_Load(object sender, System.EventArgs e)
{
// Hazırlanan İmajın Boyutu
Bitmap bm = new Bitmap(600,300);
Graphics g = Graphics.FromImage(bm);
// title
g.DrawString("Okuma-Yazma",new Font("Thoma",14),
Brushes.Black,new PointF(100,5));
Boran 52
// Gunler için grafikler
PointF symbolLeg = new PointF(40,30);
// Grafik Çerçevesi
g.DrawRectangle(Pens.Black,symbolLeg.X,symbolLeg.Y,430,245);
g.FillRectangle(new SolidBrush(getColor(0)),xy1.X,xy1.Y,20,10);
g.DrawRectangle(Pens.Black,xy1.X,xy1.Y,20,10);
g.DrawString("Bilenler",new Font("Arial",10),Brushes.Black,xy2);
xy1.Y += 15;
xy2.Y += 15;
g.FillRectangle(new SolidBrush(getColor(1)),xy1.X,xy1.Y,20,10);
g.DrawRectangle(Pens.Black,xy1.X,xy1.Y,20,10);
g.DrawString("Bilmeyenler",new Font("Arial",10),Brushes.Black,xy2);
// Grid
PointF linePoint1 = new PointF(40,70);
PointF linePoint2 = new PointF(470,70);
// Grafik Kolonları
int spacebetbars = 120;
int scale = 2;
g.DrawRectangle(Pens.Black,(j*spacebetbars)+80,
270-((values[j]*100/total)*2),80,(((values[j]*100/total))*scale)+5);
// Resim Yaratılıyor
bm.Save(Response.OutputStream,ImageFormat.Jpeg);
}
Boran 53
if(itemIndex<10)
{
switch(itemIndex)
{
case 0:
objColor = Color.Blue;
break;
case 1:
objColor = Color.Red;
break;
default:
objColor = Color.Black;
break;
}
}
else
objColor = Color.Blue;
return objColor;
}
}
Graphics g = Graphics.FromImage(bm);
satırı ilede bu bm nesnesi üzerinde çizim yaparken kullanacağımız grafik
nesnesini yarattık.
Boran 54
<DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
<HEAD>
<meta content="C#" name="CODE_LANGUAGE">
<meta content="JavaScript" name="vs_defaultClientScript">
</HEAD>
<body MS_POSITIONING="GridLayout">
<form id="GraphicView " method="post" runat="server">
<table align="left">
<tr>
<td>
<IMG id="Img1" src="BarChart.aspx" runat="server">
</td>
</tr>
</table>
</form>
</body>
</HTML>
Boran 55
Bir .Net Component yazmak
COM Server (ToplaComServer.cs)
using System;
namespace ToplaNS
{
public class ToplaClass
{
public void ToplaMethod(int
a,int b)
{
int c=a+b;
Console.WriteLine("Toplam:
{0}",c);
}
}
}
csc /t:library
ToplaComServer.cs
using System;
using ToplaNS; //toplacom.dll
icindeki namespace nin ismi
public class MyClass
{
public static void Main()
{
ToplaClass topobj=new
ToplaClass();
Boran 56
topobj.ToplaMethod(5,10);
}
}
csc ToplaComClient.cs
Toplam: 15
Boran 57
C++ Programcıları için C#
Merhaba arkadaşlar
C++ programcıları için C # isimli makalemi iki bölüm halinde sunmaya
çalışacağım. Temel olarak c# ın object orianted bir dil olması ve bir çok yönü ile
c++ ’a benzemesi nedeni ile c++ programcıların anlıyacağı tarzda c# ın
yeniliklerinden bağsetmeye başlayacağım.
· Derleme işlemleri;
· Statements
int x ;
if (x) {
// işlemler..
}
while(x){
// işlemler...
Boran 58
if (x !=0){
// işlemler...
while (x !=0){
// işlemler...
int main(){
//işlemler..
return 0;
Boran 59
Yukarıdaki kod C#‘da hata verir.
using System;
class Myclass{
Console.WriteLine("Myclass’ın
içindeki Main");
Yine C#‘da sınıfın veri elemanlarının tanımlanma mantığı C++ dan farklıdır.
class Myclass{
public:
int x,y;
void Mymethod();
protected:
int z;
Boran 60
C#‘da ise artık sınıf elemanları public, private, protected gibi özel bloklarda
tanımlanmamaktadır blok tanımlaması kaldırılmıştır. Bunun yerine aşağıdaki
tanımlama C# için geçerli olan tanımlamadır.
class Myclass{
protected int z;
private int z;
internal k;
//...
//...
· “New” operatörü
Boran 61
New operatörünün anlamı C++ ve C# da tamamen farklıdır.C++ da New
operatörü ile heap’den alan tahsis edersiniz. Fakat C#’da New operatörünü bir
sınıfın constructor’ını çağırmak için kullanırsınız.
MyClass mine ;
x=0;
ama biz bu işlemle aynı etkiyi oluşturan aşağıdaki kodu kullanmayı terçih
ediyoruz.
int x = 0 ;
· Operator Overloading
Boran 62
Operatör overloading işlemi C# da bazı kısıtlamalar ve yenilikler getirmektedir.
C# da bütün operatör overloading fonksiyonlarında “public static” ifadesi
kullanılır ve bundan kaynaklanan çok ciddi değişiklikler vardır. Bu değişiklikler
ise C# da +=, -=, *=, /=, %= operatörlerinin overload edilemez oluşudur. Bunun
yerine +, -, *, /, % operatörleri overload edilir. Yani = (Assign) işlemi sistem
tarafından otomatik olarak gerçekleştirilir. Mesela biz + operatörünü overload
ettiğimizde sistemde += operatörünü bizim yerimize overload ediyor ve bizim
+= operatörünü overload etmemize izin vermiyor.
using System;
namespace OOverloading
class Vector
public double x, y, z;
this.x = x;
this.y = y;
Boran 63
this.z = z;
x = rhs.x;
y = rhs.y;
z = rhs.z;
result.x += rhs.x;
result.y += rhs.y;
result.z += rhs.z;
return result;
Boran 64
static void Main()
Console.WriteLine("vect1 = " +
vect1.ToString());
Console.WriteLine("vect2 = " +
vect2.ToString());
Console.WriteLine("vect3 = " +
vect3.ToString());
vect4 += vect1 ;
Console.WriteLine("vect4 = " +
vect4.ToString());
Yukarıdaki örnekrte biz vector sınıfı için + operatörünü overload ettik ve daha
sonra hem + hemde += operatörünü kullandık. Ve her ikiside başarılı bir
şekilde çalıştı. Bu işlemin çıktısı aşağıdaki gibidir.
vect1 = ( 3 , 3 , 1 )
vect2 = ( 2 , -4 , -4 )
Boran 65
vect3 = ( 5 , -1 , -3 )
vect4 = ( 3 , 3 , 1 )
Binary operatörler: +, -, *, /, %, &, |, ^, <<, >>, ==, !=, >, <, >=, <=
Boran 66
Web Form Elemanlarının C# 'ta Kullanımı
Bütün Object Oriented Programlama dillerinde olduğu gibi, C#'la
yazılmış programlarda da
TextBox, Button, Label, ListBox, ComboBox, CheckBox ve RadioButton
sıkça
kullanılan bileşenlerdir.
Boran 67
belirlediğimiz yerdir.Biz bu kısımda web form elemanlarının
AutoPostBack özelliğini True atayarak,bu elemanların değerleri
Refresh anına karşı durum/içeriklerini koruyoruz.Bu koruma
derlenmiş kodumuzun içerisinde Hidden türünde bir ala içeren
web form elemanı oluşturacak ve korunmasını istediğimiz
değerleri ViewState parametresinde saklayacak...
*/
TextBox1.AutoPostBack=true;
CheckBox1.AutoPostBack=true;
ListBox1.AutoPostBack=true;
ListBox2.AutoPostBack=true;
}
Boran 68
}
TextBox1.Text="";
}
Boran 69
For Döngüsü ile ListBox1'deki bütün elemanları ListBox2'ye taşıyoruz
ve ardından
ListBox'ın Clear() metodunu kullanarak ListBox1'i temizliyoruz...
Boran 70
kullanarak, ListBox1'deki seçili metnin Label1'de görünmesini
sağlıyoruz...
Boran 71
myxmlWrtr.WriteStartElement("Siteler");
// Siteler adında bir alan oluşturuyoruz ve ardından for döngüsü
ile bu
// Listbox2'deki değerleri bu alana ekliyoruz...
for (int i = 0 ;i <= ListBox2.Items.Count-1; i++)
{
myxmlWrtr.WriteStartElement("Ad");
myxmlWrtr.WriteString(ListBox2.Items[i].Text);
myxmlWrtr.WriteEndElement();
}
// Xml Dosyasına yazma işlemini bitiriyor ve dosyayı kapatıyoruz.
myxmlWrtr.WriteEndDocument();
myxmlWrtr.Close();
}
Boran 72
Burada ListBox2'deki seçili veri üst satırdaki veri ile
değiştirilmektedir.Üste satıra alma
işleminde verinin en üstteki olma olasılığında (En üstteki veri
olması ListBox1.items[0]
demektir.) compiler'ın hata vermemesi için yine kontrol
yapılmaktadır.Ardından Kayık Yöntemi
ile verinin diğeri üsteki ile yer değiştirmesi sağlanıyor.
Boran 73
private void CheckBox1_CheckedChanged(object sender,
System.EventArgs e)
{
Label1.Text = "CheckBox1 Durumu :" + CheckBox1.Checked;
if (CheckBox1.Checked)
{
Label1.BackColor = Color.Aqua; // Color Metodu System.Drawing
// NameSpace'inden gelmekte
}
else
{
Label1.BackColor = Color.Beige;
}
}
Mustafa ÖZLÜ
Boran 74
MSIL Yapısını İnceleyelim
Giriş
.Net mimarisinin bize sağladığı birçok avantajdan bahsettik şimdiye kadar. Bunu nasıl
yaptığını ise .Framework'u incelerken karşımıza bir katman olarak çıkan Common
Language Runtime(CLR) bize inanılmaz bir avantaj sağlıyordu: birden fazla dili kullanma.
Bu çok ciddi bir avantaj eğer Visual Basic biliyorsam Visual Basic .Net ile yazılım
geliştirebilirim, eğer C# biliyorsam onunla, eğer Java biliyorsam J# ile. Bu diller saymakla
bitmez demiştik; bugün itibariyle .Net platformunda 37 farklı dil destekleniyor. Bu farklı
dil desteğini bize sağlayan ise ara dil mekanizmasıydı. Bu makalede Microsoft Intermedia
Language'ı yani MSIL'i inceliyor yapısının derinleklerine iniyor olacağız.
Gereksinimler
Bu makalede anlatılanları uygulayabilmeniz için öncelikle bilgisayarınızda .Net Framework
yüklü olmalıdır. Örnek kodları C# dilinde yazdığım için temel düzeyde C# biliyor olmanız
gerekmektedir. Makalenin ilerleyen kısımlarında değineceğimiz Ildasm aracını ve C#
derleyicisini kullanacağımız için bu konularda da temel bilgiye sahip olmak
gerekmektedir.
Son bir özet çıkaracak olursak: MSIL nesneye yönelik programlamayı destekler; .Net
Framework içerisindeki veri tipleri ile çalışır(System.String, System.Int32 gibi);
Yönergeler(instructions) birçok tip olarak sınıflandırılabilir: loading(ld*) yani yükleme,
aritmetik işlemler, mantıksal ifadeler, bellek ayırımı, hata yakalama, storing(st*) yani
saklama gibi. İsterseniz genel bakışı burada bitirelim ve incelemeye başlayalım MSIL'i.
MSIL'i İnceleyelim
Hemen bir örnek kod ile başlayalım, basit bir C# kodu ile "Merhaba Dünya" diyelim ve
ardından onun nasıl ara dile derlendiğini inceleyelim:
Az sonra anlatacağımız Ildasm aracı ile oluşacak ara dil kodunu açacak olursak:
Boran 75
Şimdi de bunların ne anlama geldiğini inceleyelim:
ldstr açılımına baktığımızda load string yönergesi var; "Merhaba Dunya" ifadesini stack içerisine
yüklüyoruz. Call yaptığımız bir metodu çağırdığımızın ifadesi; console sınıfına ait WriteLine
methodunu çağıyor. [mscorlib] ifadesi ise bu metodu barındıran dll dosyanın adı yani mscorlib.dll.
Son olarak System ifadesi de console sınıfını içeren isim uzayı(namespace).
Görüldüğü aslında IL kodu çok karışık birşeyler içermiyor, eğer basitçe bir assembly dilinin ne
yaptığı konusunda bilgi sahibi iseniz sizin için MSIL'i öğrenmek de çok kolay olacaktır.
Şimdi biraz daha detaylı bir örnek görelim, içerisinde aritmetik işlemler olan bir C# kodu yazalım:
// C# program kodu
int i = 10;
if(i!=20)
i = i*20;
Console.WriteLine(i);
Kısa bir C# kodu ne hale geldi diyeceksiniz, satır satır inceleyelim. İncelemeye geçmeden
IL_ ile başlayan satır ifadeleri okumamızı kolaylaştıracaktır.
ldc.i4.s ifadesinin karşılığı şu; ldc yani load constant , i4 yani four byte integer, s yani
single byte argument. Elimizdeki 10 sabitini stackin içerisine yerleştiriyoruz, bunu
yaparken tipini de tanımlıyoruz.
stloc.0 ifadesinin karşılığı şu; stloc yani store in location, 0 yani sıfırıncı değişken (zeroth
variable). 10 sabitini stack içerisinden alıp değişken numarası 0 olan bir değişken
içerisinde tutuyoruz.
ldloc.0 ifadesinin karşılığı şu; ldloc yani load from location, 0 yani sıfırıncı değişken(zeroth
variable). Sıfırıncı değişkenden gerekli değer okunur ve stack üzerine eklenir.
ldc.i4.s ifadesinin karşılığı şu; ldc yani load constant, i4 yani four byte integer, s yani
single byte argument. Integer sabiti olarak 20'yi stack'e ekler.
Boran 76
beq.s ifadesinin karşılığı şu; beq yani branch of equal to, s yani single byte argument.
Stack içerisinde iki değeri alır ve karşılaştırır, eğer eşitlerse verilen IL_ ifadesine geçiş
yapılır.
mul yani multiply stack'de yer alan iki sayıyı alır ve birbiri ile çarpar. Sonucu yine stack'e
geri yollar, dönen çarpım sonucu stack içerisinde en üstte yer alacaktır.
stloc.0 stack içerisinde en üstte yeralan ifadeyi alır, bu durumda çarpım sonucu
olmaktadır. Bu değeri i değişkeninin içine atar.
call yani metodun çağırılması işlemi gerçekleşir. Az önceki örnekte olduğu gibi WriteLine
metodu çağırılmaktadır. [mscorlib] ifadesi ise bu metodu barındıran dll dosyanın adı yani
mscorlib.dll. Son olarak System ifadesi de console sınıfını içeren isim uzayı(namespace).
Sonuç ekrana görüntülenecektir.
Boran 77
ILDASM aracı ile uygulamalarınızda hata ayıklarken ciddi anlamda yararlanabilirsiniz, ama
tabiki MSIL kodu üzerine oldukça iyi seviyede bilgi sahibi olmanız gerekmektedir.
Boran 78
İsterseniz bu yazıyı burada bitirelim ve bundan sonraki yazımızda ILDASM ile hatalı
yazmış olduğumuz bir C# programının MSIL kodunda hata ayıklayalım.
Boran 79