You are on page 1of 79

C ‘YE GİRİŞ (1)

C# Bölümünden herkese merhaba.


Bundan böyle düzenli olarak bu bölümde temelden başlamak suretiyle C# ile ilgili
bilgiler vermeye çalışacağım. Amacımız belli bir konu sırası ile mümkün olduğunca
sık güncelleyerek bu bölümü size aktif olarak sunabilmek.

Her neyse lafı daha fazla uzatmadan ilk makalemize başlıyalım.


Yazılım teknolojilerini takip edenler eminim C# ismini uzun bir süre önce duymaya
başlamışlardır. Peki nedir bu C#?

Microsoft'un geliştirdiği ve yine Microsoft'a göre Windows İşletim


sisteminden sonra BT sektöründeki en büyük gelişme olan ve yatırımlarının %80' nini
bu çalışmalara ayırdığı .NET 'in bir parçası. Yada şöyle diyelim.
.NET'in resmi dili.

Dinamik sayfalar ile birlikte internet üzerindeki web siteleri programlanabilir


ekranlar halini aldı. Bu sayfaları asp,php gibi bir takım dillerle hazırlıyabiliyorduk.
Özellikle JAVA ile birlikte daha kompleks, daha ciddi servisler hazırlanabilir hale
gelmişti. İşte bu noktada Microsoft tarafında .Net Framework Beta Piyasaya sürüldü.
(Şu anda benim kullandığım Beta2 versiyonu) Farklı modüllerden meydana gelen bu
ürünün bir parçasınıda C# oluşturdu.

C# haricinde Visual Studio.NET aracılığı ile, gelişmiş başka diller


ilede bu servisler geliştirilebilir. Örneğin Dünya üzerinde en çok bilindiği ve
kullanıldığı söylenen VBasic yada çok güçlü bir dil olan C++. Peki madem öyleyse niye
C#. Nedeni şu;

C# .NET Framework ile sıfırdan yaratılmış bir dil. Dolayısıyla .Net'in


bütün özellikleri ile uyumlu çalışabiliyor. Ayrıca tam anlamıyla Object Oriented bir dil.
Nesneye yönelik programlamanın getirdiği bütün avantajları bünyesinde barındırıyor.
Temelde Syntax'ı Java'ya çok benziyor. C++ ve Java ile uğraşanların bu dile kolayca
adapte olacağını düşünüyorum.

Ben bu sayfalarda hazırladığım kodları Visual Studio.NET' ile


hazırlıyorum. Eğer sizin böyle bir imkanınız yok ise Microsoft'un sitesinden Framework SDK
yı indirerek(Yanlız yanılmıyorsam 110 MB civarı.) bu uygulamaları gerçekleştirebilirsiniz.
C# ile ilgili bu kısa ön bilginin üzerine yine kısa bir kod ile bu makalemize burada son
verelim.

class IlkKod
{
public static void main()
{
Console.WriteLine("Bir Sonraki Yazida Gorusmek Uzere");
}
}

Boran 1
C DEĞİŞKEN VE METHOD TANIMLARI (2)

Bu makalemizde C#' ta değişken ve method tanımlama işlemleri üzerinde


duracağız. Değişken tiplerini tanıyıp kullanım şekillerine baktıktan sonra Method
tanımlama
yöntemlerini inceleyeceğiz. Ardından değişkenlerin kullanım yerlerine göre oluşturduğu
fark-
lılıkları inceleyerek yazımıza son vereceğiz.

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.

int i; //Değişken Tipi ve Değişkenin Adı


veya
int i=0; //Değişken Tipi - Değişkenin Adı - Değeri

-Aynı işlem string tipte bir değişken içinde tekrarlanabilir.

string ad; //Değişken Tipi ve Değişkenin Adı


string ad="AHMET"; //Değişken Tipi - Değişkenin Adı - Değeri

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.

Tipi Uzunluğu Boyutu


Byte 0-255 8 Bit integer
16 Bit
Char -
character
Double - 15-16 digits
Float - 7 digits
32 Bit
int -2.147.483.648 ile 2.147.483.647 arasında
integer
–9.223.372.036.854.775.808 ile 64 Bit
long
9.223.372.036.854.775.807 integer
16 Bit
short -32.768 ile 32.767 arasında
integer

METHOD TANIMLAMA

İşe bir önceki makalede yazdığımız örnekle başlıyalım.

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";

public static void main()


{
string yer="method değişkeni";
Console.WriteLine(yer);
Test baglan = new Test();
baglan.EkranaBas();
}
public void EkranaBas()
{
Console.WriteLine(yer);
}
}

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.

Bu yazımızda yukarıdaki sorulara cevap arıyacağız. Konuyu kavrıyabilmeniz açısından bir


önceki
makaleyi ("C#'da Değişken ve Method Tanımlamak") okumanızı tavsiye ederim.

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;

public class Merhaba


{
int[,] myArray; // İki boyutlu bir dizi tanımladık.

public static void Main()


{
Merhaba baglan = new Merhaba();

Boran 5
baglan.EkranaBas();
}

public void EkranaBas()


{
myArray = new int[3,3];

// Dizinin Sınırlarını Belirledik


// For döngüleri ile dizi elemanlarının içeriğini girip ekrana
basıyoruz.

for(int i=0 ; i<=3 ; i++)


{
for(int j=0 ; j<=i ; j++)
{
myArray[i,j] = i+j;
Console.WriteLine("myArray[{0},{1}]= {2}",i,j,myArray[i,j]);
}
}

}
}

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.

public void EkranaBas(int row , int col)


{
myArray = new int[row,col];

for(int i=0 ; i<=row ; i++)


{
for(int j=0 ; j<=col ; j++)
{
myArray[i,j] = i+j;
Console.WriteLine("myArray[{0},{1}]= {2}",i,j,myArray[i,j]);
}
}
}

Evet bu makalemizde fonksiyon ve array'leri inceledik. Bir daha ki makalemizde C#


Statement'larını
inceleyeceğiz. Aslında bu ifadelerden biri olan For Statement'ını bu makalemizde gördük
sayılır.

Boran 6
C# C SHARP A GENEL BAKIS

C# Windows uygulamaları geliştirmek için C++ ve Visual Basic


programlama dillerine alternatif olarak Visual Studio .NET ile
birlikte gündeme gelen bir uygulama geliştime dilidir.

C#, bize Visual Studio’da yalnızca C++ ile erişebildiğimiz


yerlere ulaşabilmemizin yanısıra Visual Basic kadar kolay bir
kullanım sağlar. Özellikle .NET için geliştirildiğinden .NET kod
yapısına en uygun dil olarak bakabiliriz C# ’a. Bu nedenle C#, .NET
framework’ünü daha kolay ve daha etkin kullanır. Orta seviye bir
programla dili olması ise Visual Basic ve C++’ın en iyi özelliklerini
içermesini ve tam bir OOP (Object Oriented Programming) ortamı
sunmasını sağlar.

C#’ı .NET framework’ünden ayrı olarak incelemek yerine


bütünün bir parçası olarak ele almak gerekir. Çünkü .NET ile
geliştirilen CLR (Common Language Runtime – JVM[Java Virtual
Machine]’e benzeyen ve birbirinden farklı dillerin IL(Intermediate
Language)’e compile edilerek oratak çalışmasını sağlayan yapı
olarak tanımlayabiliriz), .NET kodlarının ortak çalışmasına izin
vermektedir. Bu şu anlama gelir ister C#, ister C++, ister Visual
Basic, uygulamamızı hangi platformda yazarsak yazalım çatımız
hep aynıdır.

.NET, genel amaçlı yazılmış windows platformu


programlarında bir devrimdir. .NET’in sağladığı birçok avantaj
vardır; kullanımı kolay nesne modellemesi, Garbage Collection’ı
sayesinde yaratılan kaynakların otomatik olarak temizlenmesi,
SQL ve ADO spesifik Data Access, ASP .NET sayfalarının
oluşturulmasına yarayan geliştirilmiş library’ler ve bunlar gibi
birçok yapı. Ancak; her ortam için o ortamın özelliklerine ulaşmak
elbette belirli mekanizmalar gerektirir. Örnek verecek olursak
Windows, C ve C++’da yazılmış bir dil olduğundan yönetim yine
C,C++ kodundan ulaşabildiğimiz Windows API ile sağlanır (Bu,
Visual Basic’in Windows API’nin bütün özelliklerine kolay erişim
sağlayamamasının nedenidir). C#’ın gerçek faydası burada ön
plana çıkmaktadır, C# .NET framework’ü için sıfırdan başlanarak
tasarlanmış ve bu dilin yazım ve dil özellikleri .NET’in sunduğu
kolaylıklardan basit bir şekilde yararlanabilmesi için
geliştirilmiştir.

Bir örnek verecek olursak;

System.String .NET class library’sinde bir class’tır ve case


convertion’ları, substring’lerin ayıklanması ve string ifadelerin
trim’lenmesi gibi bir çok method’a sahiptir. C# compiler’ı bu class’ı
otomatik olarak tanıyan kendi string keyword’üne sahiptir.

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.

.NET framework’ü, kullanılan kaynakları boşaltmakta çok


başarılıdır. Bu başarının sırrı ise managed code içerisindeki
değişkenlerin stack yerine managed heap’de tutulmasıdır. C# bu
gibi işlemleri bizim yerimize otomatik olarak yapmaktadır. Tabiiki
.NET platformunda Managed C++ ve VB.NET de aynı özelliklerden
C# gibi faydalanabilmektedir. Bu yapının sağlanabilmesi ise Visual
Basic ve C++’ın yapısında gerçekleştirilen bir takım değişikliklerle
mümkün olmuştur. Bu da Visual Basic ve C++ açısından
bakıldığında bir upgrade anlamına gelmektedir. Yapıları ne kadar
upgrade edildiyse de yeni bir platform için VB ve C’ye geçmişten
gelen yazılım geliştirme dilleri olarak bakmak yerinde olacaktır. Bu
iki dil bu anlamda .NET platformunda yazılım geliştirirken
geçmişten gelen alışkanlık ve syntax yapıları yüzünden tam
anlamıyla .NET için dizayn edilmemişlerdir; bu da yazılım
geliştirirken C#’a göre bu yazılım geliştirme dillerini dezavantajlı
hale getirir. Hatta bu yüzden VB.NET syntax’ının hala tam
anlamıyla Object Oriented Programming’e göre dizayn edilmediği
tartışmasını ortaya çıkarmıştır.

C# ise karşımıza tertemiz bir defter yaprağı gibi çıkmaktadır.


Bunun nedeni ise Microsoft’un C#’ı tam anlamıyla .NET çizgisine
göre geliştirmiş olmasıdır. Object Oriented Programming için
gerekli syntax dizaynı ve program yazmayı kolaylaştıran yapısı
C#’ı .NET framework’ünde çalışmak için mükemmel bir dil haline
getirmiştir.

C# tam anlamıyla bir Object Oriented Programming dilidir. Bu


özellik ise sadece C#’ın taşıdığı bir özellik değil tabiiki. C++’ta
Object Oriented Programming yapısına sahiptir hatta VB bile
Object Oriented olarak tanımlanmıştır. Buna rağmen C++ ve VB
açısından olaya yaklaştığımızda birtakım problemlerle karşılarız.

C++’ı ele aldığımızda karşımıza tam anlamıyla Object


Oriented Programming için geliştirilmiş ve dizayn edilmiş bir
programlama dili çıkar ancak geliştirildiği zamanlarda Object
Oriented Programming yapısında kodun yeniden kullanımı gibi bir
düşünce yoktu. Klasik C++ kodu bütün dilleri desteklemez ve
klasik C++’ın çalışabilmesi için, inherit edeceğiniz class’ın orijinal
source’undan class header’larına ulaşmanız gerekmektedir.

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.

Diğer bir yandan VB COM yazma platformu sağlayan ve


COM’un karmaşık yapısını uygulama geliştirenlerden gizleyen bir
yapıya sahiptir. Ancak çoğu Object Oriented Programming
uzmanının da söylediği gibi VB gerçek anlamda OOP modeline
sahip değildir çünkü inheritence’ı desteklemez.

C# ise her iki dünyanın avantajlarını bize sunmaktadır. Tam


anlamıyla inheritence’ı destekler fakat bunun yanısıra .NET
framework’ü source dosyalarımıza ulaşmadan inheritence
sağlayabilmek için compile edilmiş durumda bulunan library
dosyalarını (assembly) sağlar. Bu sayede .NET programcılık
tarihinde ilk kez programlama dilleri arasında çapraz geçişlere izin
veren ve gerçek anlamda bir yeniden kullanım olanağı sağlayan bir
platform olmuştur.

Inheritence bir class’ın içerisinde başka class’ları base


almamızı sağlayan Object Oriented Programming modelin bir
özelliğidir. Örneğin standart olarak kullandığınız bir menu,toolbar
ve statusbar yapısı var, bir form üzerinde ilgili standartlarınızı
yerleştirdiniz, başka bir formda da aynı özellikleri kullanmak
istediğinizde tek yapmanız gereken oluşturduğunuz ilk formu base
almak ve yeni formunuza inherit etmek. Yeni formunuz inherit
ettiğiniz formun bütün özelliklerini içeren yeni bir form olarak
karşımıza çıkacaktır. Development tarafından baktığımızda bu
işlem bize zaman kazandıran ve yeniden kullanım imkanı sağlayan
bir yapıdır.

C# orta seviye bir programlama dilidir. Bir sıralama yapacak


olursak C#’ın bu sıralamadaki yeri aşağıdaki gibi olacaktır.

· Assembly

o C,C++

§ C#,J++

· Visual Basic

o VBA, Scripting Dilleri

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#, Visual Basic ile C++ arasında bulunan boşluğu gidermek


için dizayn edilmiştir. C#, C++ ile yazılabilen ve yazılırken C++
kadar zor olmayan aynı zamanda Visual Basic’ten daha yüksekte
program yazmak isteyen yazılımcıları hedef almıştır. C++ ve VB
arasındaki boşluğu dolduran ve pek tatmin edici olmayan J++ bu
durumuna rağmen C# ile birçok yönden benzerlik göstemektedir.
C#, C++’ın syntax’ına çok benzeyen bir syntax’a sahiptir ve C++’ın
birçok özelliğini destekler örneğin inheritence (multiple
olmamasına rağmen). Bu nedenle C++ programcıları C#’ı çok
kolay bir şekilde öğrenebileceklerdir. Visual Basic programcıları
kendilerini yepyeni bir syntax ve birçok object oriented kavramı ile
karşı karşıya bulacaklardır ancak C#’ı öğrenmek, C++’ı
öğrenmekten çok daha kolaydı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.

Diğer taraftan, C++ developer’lara hangi değişkenin hafızada ne


kadar kalacağının ayarını yapma imkanı vermek ve böylelikle
hafızanın daha etkin kullanımını sağlamakla kalmaz, bunu
nerdeyse zorunlu kılar. C++’da yazılmış programların memory
management bug’larına maruz kalmaları ve hafızada kayıplara yol
açması Visual Basic’de gerçekleşmez.

C# memory management’ta Visual Basic’in yolunu izler, yani


sorumluluk dilin kendisindedir. Ancak VB’nin aksine C#’da
memory’yi kendiniz sınıflandırmak isterseniz yazdığınız kodun bir
bölümünü unsafe olarak belirtebilir ve sonra da C++’da olduğu
gibi Memory için yer ayırıp daha sonra bu kısmı boşaltabilirsiniz.

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#.

Temel Programlama ve C# (1)


Value Tipleri ve Tanımlanması

Value tipleri için C#, C ve C++ programcılarının seveceği bir


tanımlama syntax’ına sahiptir.

Anlaşırlılık sağlamak amacıyla her tanımlama için bir


statement kullanılabilir veya alternatif olarak aynı anda birden
fazla tanımlama yapılabilir.

// Basit Tanımlama
int i;

// Bileşik tanımlama
int i,j,k;

Tek yada bileşik tanımlamalar sırasında değişkenlere


başlangıç değerleri de atanabilir.

// Basit bir tanımalama ve initializasyon


int i=5;

//Bileşik bir tanımlama ve initializasyon


int x=3,y=8,z=-1;

C# aynı zamanda C ve C++ gibi for ve loop döngülerinin


başlangıcında değişken tanımlama ve initializasyona izin verir.

for (int j=0;j<5;j++)

C# memory buglarını önlemek amacıyla tanımladığınız


değişkenin bir değer atamasına tabi tutulup tutulmadığını compile
sırasında inceler. Bu işlem sayesinde atanan bu değerin işletim
sistemi tarafından programınızın akışı sırasında memoryden
release edilmesi engellenmiş olur.

Boran 11
using System;
public class ForcedInit
{
public static int Main()
{
int k;
Console.WriteLine(k);
return 0;
}
}

Yukarıdaki kodu compile ettiğimizde bir compiler hatası ile


karşılarız: “use unassigned local variable k”. Programı hatasız bir
şekilde derleyebilmek için k değişkenini initializasyona tabi
tutmamız gerekir.

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.

Referans Tipleri ve Tanımlanması

Referans tiplerinin bir instance’ının yaratılması sırasında new keyword’ü kullanılır.


new keyword’ü kullanıldığında C# referans tipinin bir instance’ını heap’de yaratır ve ilgili
instance’ın referans değerini döndürür; bu sayede geri dönen referansı bir değişkende
tutabiliriz.

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;
}
}

Aynı objeye birden fazla farklı referans atamak mümkündür.

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;
}
}

Bir objeye referans verildiğinde referans’ı destroy etmek için referans’ın


tanımladığı nesneye null değeri atamak yeterlidir. Bu önemli bir işlemdir çünkü Common
Language Runtime (CLR) ile yönetilen Garbage Collector (GC) ilgili nesneyi otomatik
olarak memory’den release etmek yani işini yapabilmek için bunu bilmek zorundadır.

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();

//Aşağıdaki kod ise ilgili objeyi Garbage Collector(GC)'i

//kullanarak memoryden de-allocate etmek için hazırlıyor.

objA=null;

return 0;
}
}

Periyodik olarak GC (Garbage Collector) referans’ına null değeri atanmış objeleri


tespit eder ve onların otomatik olarak memory’den de-allocate edilmesini sağlar.

Değişken Tipleri ve Dönüşümleri

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

Value ve referans tipleri arasında dönüşümler mümkündür. Stack’te tutulan bir


value tipinin heap’de tutulan bir referans tipine dönüştürülmesi işlemine ‘boxing’, heap’de
tutulan bir referans tipinin stack’te tutulan bir value tipine dönüştürülmesi işlemine ise
‘unboxing’ adı verilir.

using System;
public class BoxingExample
{
public static int Main()
{
object objA;
int i,j;

//i stack'te tutulan value tipinde bir değişkendir.


i=10;

//Bu işlem ile i'ye heap'de bir referans değeri atanır


(boxing)
objA=(object)i;

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;
}
}

Unboxing işlemi sırasında heapde tutulan referans tipinin değerinin stack’de


tutulan value tipinin değeri ile uyumlu olmasına dikkat etmek gerekmektedir. Aşağıdaki
örnekte int değerini byte değerine unbox ederek bir runtime hatası oluşmasına neden
olunmuştur. Boxing ve unboxing işlemleri ile ilgili birtakım alıştırma kodları yazmak bu tip
işlemlerin anlaşılması açısından faydalı olacaktır.

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

C# array’ler için bize yeni bir syntax sunmaktadır.Array tanımlaması sırasında


köşeli parantezler kullanılır ve tanımlama işlemi sırasında değerler atanabilir.

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;
}
}

Bu yöntem ile 2,3 ve çok boyutlu arrayler tanımlanabilir.

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.

protected bool[,] MyBool;

İstenildiği takdirde array dinamik olarak da oluşturulabilir. Aşağıdaki örnekte array


ilgili class’ın constructor’ına eklenerek class yaratıldığında dimension’ı dinamik olarak
tanımlanan bir dizi yaratılması sağlanmıştır.

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;
}
}

Bütün C# array’leri System.Array tipinden inherit edilir ve bu


bize birçok avantaj sunar. Aşağıdaki örnekte System.Array
class’ının birkaç method’unu ve avantajlarını görüyoruz.

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

Enumarationlar kişiye özel integer tiplerdir. Enumaration


tanımlandığında tanımlanan tipin alabileceği değerler belirlenmiş
olur. Enumarationlar ile geliştirdiğimiz class’ın içerisine
istenmeyen değerlerin programcı tarafından assign edilmesini
engeller ve intellisense özelliği ile programcıya kullanılabilecek
parametrelerin değerlerini göstermeden programın kolay
kullanımını sağlarız.

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

Program içerisinde hiç değişmeyecek değerler kullanmak istediğimizde sabitler


yani constant kullanılır. Constant tanımlama aynı zamanda client programcılarına
kullanabilecekleri limitleri göstermek açısından da faydalı olabilir.

abstract public class Deneme


{
public const int MaxRows=50;
public const int MaxCols=100;
}

C#’ta Program Akış Kontrol Mekanizmaları

Data tipleri hakkında birçok noktaya değindikten sonra şimdi de akış kontrol
mekanizmalarına göz atabiliriz.

Fonksiyonlar

Fonksiyonlar programın akışı sırasında en çok başvurduğumuz yapılardır.


Fonksiyon kullanmanın nedenlerini 3 şekilde açıklayabiliriz:

· Yeniden kullanım,

· Çok fazla değişen fonksiyonelliği sağlamak,

· Kodun ne yaptığını anlatmaya yardımcı olmak.

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.

Aşağıdaki örnek static bir fonksiyon tanımlayarak içeriye gönderilen iki


parametreden büyük olanını geriye döndürmektedir.

public static int Max(int value1, int value2)


{
int ReturnValue;
if (value1>value2)
{

Boran 20
ReturnValue=value1;
}
else
{
ReturnValue=value2;
}
return ReturnValue;
}

Fonksiyonu Aktif Hale Getirmek

Fonksiyonun aktif hale getirilebilmesi için fonksiyon adından


sonra parantezler ve hemen ardından içeriye gönderilecek
parametreler belirtilir ve parantez kapatılır. Aşağıdaki örnek ile
yukarıda yazılan Max fonksiyonun kullanımı görülmektedir.

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;

Console.WriteLine("Metod çağrılmadan önce x="+x);

ChangeValue(x);
Console.WriteLine("Metod Çağrıldıktan Sonra x="+x);
Console.ReadLine();

return 0;
}
}

Eğer C#’ın bu davranışını değiştirmek istersek yani fonksiyona parametre olarak


gönderilen değer üzerinde yapılan herhangi bir değişikliğin aynı zamanda değişkene de
yansımasını istiyorsak parametre tanımında geçişin referans olarak yapıldığını belirtmek
zorundayız. Bu sayede parametrede yapılan bir değişiklik fonksiyona gönderilen
değişkene yansıyacaktır. Bu işlemi gerçekleştirirken tek dikkat etmemiz gereken şey
fonksiyona gönderilen parametrenin bir değere sahip olması yani kullanılmadan önce
initialize edilmesi gerekliliğidir.

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.WriteLine("Metod Çağrıldıktan Sonra x="+x);

Console.ReadLine();

return 0;
}
}

Eğer initialize (değeri henüz atanmamış) olmayan bir değer


fonksiyona göndereceksek aynı zamanda gönderilen değerin ilgili
initialization işlemine tabi tutulması gerektiğini belirtmek
zorundayız bunu yapmak için ise out keyword’ü kullanılmaktadır.
Aşağıdaki örnek bu yöntem ile referanssal bir geçiş
sağlamaktadır.

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.WriteLine("Metod Çağrıldıktan Sonra x="+x);

Console.ReadLine();
return 0;
}
}

Diğer bir keyword ise içeriye gönderilecek kaç tane


parametre olacağının bilinmediği durumlarda kullanılmak üzere
geliştirilmiş params keyword’üdür. Bu sayede fonksiyon içerisine n
tane parametre gönderilebilir. Aşağıdaki örnek içeriye gönderilen
n parametreden en küçük olanı bulmaktadır.

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);

//k değişkenine FindMinimum fonksiyonuna 12 tane

//parametre gönderilerek gönderilenlerin en küçüğü


//atanıyor
k=FindMinimum(5,4,1,-1,-8,1000,34,100,1000,10001,-
100,1);

Console.WriteLine(j);
Console.WriteLine(k);
Console.ReadLine();
return 0;
}
}

Boran 24
Namespace, Value ve Referans Type'ların Kullanımı
Namespaces

Diğer .Net dilleri gibi C#’ta .NET base class library’sinde


tanımlanmış datatype’ları kullanır. Bu classlar namespace adı
altında gruplanmıştır. Namespace’e diğer bir tanımlama ile
classları kullanırken fonksiyonel bir şekilde ulaşmamızı sağlayan
logic containerlar diyebiliriz. Örnek olarak System.Winforms
namespace’i Winform applikasyonları için gerekli kontrol ve
classları içerir.

Genellikle namespace’deki ilk kelime class’ın geliştirildiği


organizasyonun adı olur. Farklı bir vendor’un verdiği isimlerle aynı
programda kullanıldığında herhangi bir olası isim benzerliğini
engellemek içinse namespacelerde genellikle uzun tanımlamalar
kullanılır.

namespace Netron.Otomasyon.OtomasyonClasses
{
//class tanımlamaları
}

using keyword’ü ile de namespaceler içerisinde bulunan


classları çalışmamıza çekeriz. namespace using keyword’ü ile
çekildikten sonra artık herhangi bir period belirtmeden namespace
içerisinde bulunan tanımlamalara ulaşabiliriz.

using Netron.Otomasyon.OtomasyonClasses;

using keyword’ü ile compile işlemi sırasında modüller


arasında herhangi bir link tanımlamış olmayız.

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

Common Laguage Specification (CLS) bir programlama dili


tarafından desteklenmesi kaçınılmaz olan bir çok datatype’ı
tanımlayan zengin bir library’e sahiptir. Bu libraryde bulunan
Boolean, string, integer, kronolojik ve finansal valueların hepsi
System namespace’inin içerisinde yer alır.

Bütün typelar object type’ından inherit edilir. Böylece bir


object’in referansı herhangi bir tipdeki değişkeni tutmak için
kullanılabilir.

Long type’ın bit olarak büyüklüğü 64’e çıkarılmıştır. Bu


sayede Whistler ve XP platformlarında 64 bitlik programlar için bir
hazırlık sağlanmıştır. (64 bitlik olan bu işletim sistemleri Intel’in
yeni nesil 64 bitlik işlemcisi Itanium uyumludur)

Value ve Referans Tipleri

.NET dilleri tarafından kullanılan yada yaratılan her class


value ve referans tipleri olarak kategorilendirilebilir. Value ve
referans tipleri iki karakteristikle farklılık gösterir : hafızada
tutuldukları yerler ve atama işlemi contextlerindeki davranışları.

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.

Aşağıdaki kod ile iki value değerine atama yapılmakta ve


hafızada iki değer kopyası oluşturulmaktadır. (kodu derleyip
çalıştırmak için /unsafe switch’ini kullanın)

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;
}
}

Bu kod ise iki referans değerine atama yapmakta ve


hafızadaki tek kopyaya ulaşmaktadır.

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

Constructor’lar objeleri initialize ettiğimizde devreye giren


özel metodlardır. Eğer obje class’ı içerisinde bir constructor
tanımlı değilse bile compiler tarafından otomatik olarak boş bir
constructor sağlanır.

Bir objenin yaratılması işlemi iki aşamada gerçekleşir:

Birinci aşamada obje için memory’de alokasyon


gerçekleştirilir. Her obje new operator’ü kullanarak yaratılır. Bu
kural için herhangi bir exception yoktur. Bunu explicit olarak kod
içerisinde gerçekleştirebiliriz, yada compiler bunu otomatik olarak
yerine getirir.

int[] MyIntArray={1,2,3,4};

int[] MyIntArray1=new int[4]{1,2,3,4};

Yukarıdaki deklarasyonlar’ın her ikiside aynı işi yapmaktadır.

Bir objenin yaratılmasındaki ikinci aşamada ise constructor


çağrımıdır. Constructor new ile allocate edilen memory’i obje’ye
çevirir. İki tip constructor’ın varlığından bahsedebiliriz: static ve
instance. Instance constructor’lar objelerin initialize’ı için
kullanırlırlar. Static constructor’lar ise class’ların initialize’ı için
kullanılırlar. C++’da initialize işlemi gerçekleştirmeden new
operator’ü memory allokasyonu ve yine new keyword’ü ile daha
önceden allocate edilmiş memory’i initalize etmek mümkündür. Bu
ayrım C#’da mümkün değildir. Bu yöntem ile C# memory’deki yapı

Boran 28
okunmadan önce doğru değere atanma yapılmasını garanti etmiş
olur.

Default constructor class ile aynı isimdedir, geriye bir değer


döndürmez ve bir metod değildir (void). Default constructor’ın
herhangi bir parametresi yoktur. İstenildiği takdir de parametrik
constructor’lar tanımlanılabilir.

Constructor aynı zamanda implicit olarak static olmayan


alanları initialize işlemine tabi tutar. int, double, decimal gibi
nümerik alanlar 0’a, bool alanlar false’a Referans tipler null’a,
Struct’ların içerdiği alanların hepsi yukarıdaki yapıya uygun olarak
initialize işlemine tabi tutulurlar. Default constructor’ın bu
işlmeleri yapmasının iyi yanlarının yanı sıra dezavantajlı yanlarıda
vardır: Mesela bir tarih class’ın da yıl, ay ve gün değerlerinin 0’dan
başlamasını istemeyiz. Böyle durumda kendi constructor’ımızı
tanımlamamız gerekmektedir.

Aşağıdaki örnekte default constructor kullanan bir class ve


kullanımı görülmektedir.

using System;

class Tarih

public short Gun,Ay,Yil;

class Class1

Boran 29
[STAThread]

static void Main(string[] args)

Tarih a=new Tarih();

Console.WriteLine("Yıl:{0}",a.Yil);

Console.WriteLine("Ay:{0}",a.Ay);

Console.WriteLine("gün:{0}",a.Gun);

Console.ReadLine();

Bu class’ı test ettiğimizde Ay, Gun ve Yıl değerlerinin 0’a set


edildiği rahatlıkla görülmektedir. Default constructor’ı devre dışı
bırakıp kendi constructor’ımızı yazmak istersek kodumuz
aşağıdaki şekilde olacaktır:

using System;

class Tarih

public short Gun,Ay,Yil;

public Tarih()

Gun=1;

Ay=1;

Yil=1970;

Boran 30
}

class Class1

[STAThread]

static void Main(string[] args)

Tarih a=new Tarih();

Console.WriteLine("Yıl:{0}",a.Yil);

Console.WriteLine("Ay:{0}",a.Ay);

Console.WriteLine("gün:{0}",a.Gun);

Console.ReadLine();

Bu kod çalıştığında ise 1.1.1970 tarihi ile karşılaşırız. Default


constructor ve kendi oluşturduğumuz constructor arasındaki fark
açık bir şekilde görülmektedir.

Constructor’lar tıpkı metod’larda olduğu gibi overload


edilebilirler. Bu sayede class’ımızın farklı initialization işlemlerine
tabi tutulması sağlanılabilir. Overload etme işlemi gayet basittir.
Class ile aynı isimde ve diğer constructor’dan farklı parametreler
kabul eden bir tanım vererek bunu sağlayabiliriz. Az önce
gördüğümüz örnekteki constructor’ı overload edecek olursak:

Boran 31
using System;

class Tarih

public short Gun,Ay,Yil;

public Tarih()

Gun=1;

Ay=1;

Yil=1970;

public Tarih(short Day,short Month,short Year)

Gun=Day;

Ay=Month;

Yil=Year;

class Class1

[STAThread]

static void Main(string[] args)

Tarih a=new Tarih();

Tarih b=new Tarih(2,2,2002);

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 short Gun,Ay,Yil;

public Tarih():this(1,1,1970)

public Tarih(short Day,short Month,short Year)

Boran 33
Gun=Day;

Ay=Month;

Yil=Year;

class Class1

[STAThread]

static void Main(string[] args)

Tarih a=new Tarih();

Tarih b=new Tarih(2,2,2002);

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();

Birinci constructor’da yaptığımız :this(1,1,1970)


yönlendirmesi ile üç parametre kabul eden ikinci constructor’ı
çağırmış olduk. Bu yönteme initializer list adı verilmektedir. Bu

Boran 34
noktada bilmemiz gereken bir kural ise bir initializer list içerisinde
tanımlı metod’un kendi kendini çağıramamasıdır.

Class içerisinde bazen readonly değişkenler kullanmak


istiyebiliriz. Yani değeri bir kere assign edildikten sonra kullanıcı
tarafından değiştirilmesini istemediğimiz değişkenler. Bu şekildeki
değişkenler class içerisinde aşağıdaki şekilde tanımlanılabilirler:

public readonly int MinYil=0;

Bu tanımlama ile sonradan değiştirilemeyecek bir değer


ataması yapmış oluruz. Fakat bazı durumlarda bu değerin class’ın
yaratımı içerisinde değişmesini isteyebiliriz. Mesela class
içerisinde bir array’imiz var ve initialization sırasında bu array’in
Max range’inin belirlenmesini istiyoruz. Bu durumda bir şekilde
kullanıcıya readonly olan bu değere bir kereye mahsus bir
assignment şansı vermek zorundayız. Bu gibi durumlarda ise
constructor’ları kullanmak zorunda kalırız.

Bir örnekle bakacak olursak:

using System;

class MyArray

public readonly int MaxRangeOfArray;

public int[] MyArr;

public MyArray(int MaxRange)

MaxRangeOfArray=MaxRange;

Boran 35
public void CreateArray()

MyArr=new int[MaxRangeOfArray];

class Class1

[STAThread]

static void Main(string[] args)

MyArray a=new MyArray(1);

a.CreateArray();

a.MyArr[1]=2;

Console.ReadLine();

MaxRangeOfArray değişkenine yapmış olduğumuz atama


sadece constructor içerisinde gerçekleşebilir. Constructor dışında
herhangi bir metod içerisinde bu değişkene yapılacak atama
compiler’ın hata vermesine neden olacaktır.

CONSTRUCTORS
using System;

class AspNedir
{
public int number=3;

public AspNedir() // Constructor


Methodumuz
{
number = 5;

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.

Şimdi yukarıda ki class'ımızı çağıracak olan methodumuzu yazalım.

public static void Main()


{
AspNedir test = new AspNedir();

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;

public AspNedir(int newNumber) //


Dışarıdan değer alan Constructor
Methodumuz
{
number = newNumber;
}
public int getNumber()
{
return number;
}
}
Dışarıdan değer alan Constructor'ı ise şu şekil de çağırabiliriz.
public static void Main()
{
AspNedir test = new AspNedir(12);

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;

public int testMethod()


{
int deger = 3;
return deger;
}
public static void Main()
{
int deger = 5;
AspNedir test = new AspNedir();
Console.WriteLine("Değişkenin testMethod Değeri ="+test.testMethod());
Console.WriteLine("Değişkenin Main Fonksiyonuna Ait Değeri ="+deger);
Console.WriteLine("Değişkenin Class Değeri ="+test.deger);
Console.ReadLine();
}
}
Yukarıda ki örnekte görüldüğü gibi integer tipteki "deger" değişkeni aynı uygulama
içinde farklı bloklarda
üç kere tanımlanmasına rağmen hata vermedi. Bir değişkenin değerini ekrana basmaya
kaltığımız zaman,
değer ilk önce bulunulan blok içinde aranır. O blok içinde eğer tanımlı böyle bir değişken
varsa değeri
ekrana basılır. Aksi taktirde Class seviyesine çıkılarak istenen değişkene bakılır. Yoksa
uygulama zaten
böyle bir değişken tanımlı değil diye hata vericektir.

Boran 39
C#' ta IO (Girdi/Çıktı) İŞLEMLERİ

Bilgisayarımızın sürücüleri, dosya ve klasör yapıları ile ilgili gerekli


bilgileri almamızı yada herhangi bir text dosyası yaratma ,içine bilgi girişi yada
içindeki bilgileri okuyabilmemizi sağlıyan işlemlere IO (input/output) işlemleri
diyoruz.
Yukarıda saydığım işlemleri yapabilmemizi sağlıyacak olan gerekli class ve
methodlar .NET geliştirme ortamında System.IO namespace 'i içinde yer alır.
Dosya ve klasörler üzerinde işlem yapmamızı sağlıyan dört sınıf vardır. Bunlar;

• Directory
• DirectoryInfo
• File
• FileInfo

Directory ve File Sınıfları yeni bir klasör yada dosya yaratma-silme


işlemlerinizi yaparken ,DirectoryInfo ve FileInfo ise adından da anlaşılacağı gibi
daha çok, ilgili klasör yada dosya hakkında çeşitli bilgileri almanızı sağlıyacak
olan sınıflardır.
using System;
using System.IO;//System.IO namespace'i
namespace AspNedir
{
public class systemIO
{
public static void Main()
{
//Driver Listesi Diziye Atılıyor.
string[] suruculer = Directory.GetLogicalDrives();
foreach (string liste in suruculer)
{
Console.WriteLine("surucu={0}",liste);
}
//İstediğim Herhangi Bir Dosyaya En Son Ne Zaman
//Erişildiğini de File Sınıfının GetLastAccessTime
//Methodu ile Öğrenebilirim.
string d=(File.GetLastAccessTime(@"c:\aspnedir.txt")).ToString();
Console.WriteLine (d);
Console.Read();
}
}
}

Örnekte Directory sınıfının GetLogicalDrives ve File Sınıfının GetLastAccess


methodlarını gördük. Directory ve File Sınıfının diğer bazı özelliklerine
bakacak olursak.
File Directory
AppendText() CreateDirectory
Copy Delete
Create Exist
Delete Move
Exist GetDirectories

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

Directory ve File Sınıfları bu kadar. Şimdi bir örnekle devam edelim;

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");

//Dosyanın İçine Kaydedilecek Yazı


string icerik = "\nASPNEDIR \nBu yazi txt dosyasina kaydedilecek.";

//Dosya Yazmak İçin Açılıyor


FileStream myFs = myFile.OpenWrite();

char[] myArray = icerik.ToCharArray();


foreach(Char temp in myArray)
{
myFs.WriteByte(Convert.ToByte(temp));
}

//FileStream Kapatılıyor.
myFs.Close();
}
}
}

Gördüğünüz gibi IO Sınıfları ve ait olan methodların içeriği oldukça geniş


bir konuyu kapsıyor. Bu nedenle iki makaleye bölme kararı aldım.

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.

C#' ta IO (Girdi/Çıktı) İŞLEMLERİ – 2


Vektörel çarpım

İki vektörün vektörel çarpımı

/* kartezyen koordinat sisteminde


üç boyutlu iki vektörün vektörel çarpımını
matris determinantından yararlanarak (Sarruse
yöntemine göre) yapar.
yazan : mehmet kabak
E-mail : <E-POSTA>kabak@eng.ankara.edu.tr</E-POSTA>
<AC>kabak@eng.ankara.edu.tr</AC>
*/
#include <iostream.h>
#include <math.h>
#include <conio.h>
void main()
{
int i, // döngü sayaçları
j, // döngü sayaclari
k;
float a[5][3], // determinat icin kullanılacak
b[3] = {0.,0.,0.}, // dizinin ilk elemanları
c[3] = {0.,0.,0},
t = 1;
a[0][0] = 1.; // matrisin ilk elemanları
a[0][1] = 1.;
a[0][2] = 1.;
//
a[1][0] = 5.;
a[1][1] = -3.;
a[1][2] = 2.;
//
a[2][0] = 2.;
a[2][1] = 3.;
a[2][2] = 4.;
// aşağıdaki satırlar yukarıdaki ilk iki
// grubun (satırın) tekrarıdır (Sarruse y.)
a[3][0] = 1.;
a[3][1] = 1.;
a[3][2] = 1.;
//
a[4][0] = 5.;
a[4][1] =-3.;
a[4][2] = 2.;
//
a[5][0] = 0.; // matrisin son elemanlarına sıfır
// değeri atanır
a[5][1] = 0.;
a[5][2] = 0.;

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
{

public static void Main()


{
XMLClass baglan = new XMLClass();
baglan.createXMLFile("C:\\AspNedir.xml");
}

public void createXMLFile(string fileName)


{
XmlTextWriter myWriter=new XmlTextWriter(fileName, null);
// Döküman olusturuluyor.
myWriter.WriteStartDocument();
// Döküman içerisine bir açiklama alani ekleniyor.
myWriter.WriteComment("AspNedir.xml Yaratıldı");
// Personel adli etiketi olusturuluyor.
myWriter.WriteStartElement("Personel");
myWriter.WriteStartElement("SicilNo");
// Sicil Alanının Attribute'ü
myWriter.WriteAttributeString("id","1");
// Ad alani olusturuluyor ve degeri içine yaziliyor.
myWriter.WriteStartElement("Ad");
myWriter.WriteString("Oğuz");
myWriter.WriteEndElement();
myWriter.WriteStartElement("Soyad");
myWriter.WriteString("Çalışkan");
myWriter.WriteEndElement();
myWriter.WriteStartElement("Telefon");
myWriter.WriteString("02165213624");
myWriter.WriteEndElement();
myWriter.WriteStartElement("Bolum");
myWriter.WriteString("Muhasebe");
myWriter.WriteEndElement();
// SicilNo element'i kapatiliyor.
myWriter.WriteEndElement();
//Personel element'i kapatiliyor.
myWriter.WriteEndDocument();
// Döküman kapatılıyor.
myWriter.Close();
}

Boran 44
}
}

Örnektede görüldüğü gibi XmlTextWriter sınıfı aracılığı ile dosyamı yaratıyorum.


Bu classın constructor'ı dışarıdan iki parametre alıyor. Bunlarda ilki yaratılacak olan
dosyanın sistem üzerindeki yeri ve dosyanın adı. İkincisi ise System.Text.Encoding
değerinin boş olduğunu gösterir. Örnekte Main methodu üzerinden createXMLFile isimli
methodu çağırırken dosya bilgisinide parametre olarak gönderiyorum.
Belirttiğimiz dosya üzerinde herhangi bir element açmak için kullandığımız komut ise
WriteStartElement. Yaratacağımız elementin adının ise bu komuta parametre olarak
gönderiyoruz. Bu elementin alacağı normal bir değer ise WriteString, Attribute ise
WriteAttributeString komutunu kullanıyoruz. WriteAttributeString komutu
çağırıldığında
dışarıdan iki parametre alır. Bunlardan ilki Attribute adı, diğeri ise değeridir. Dosya ile
işimiz bittikten sonra ise tek yapmamız gereken .Close ile kapatmaktır.

public void readXMLFile(string fileName)


{
XmlTextReader xmlreader = new XmlTextReader(fileName);
while(xmlreader.Read())
{
Console.WriteLine(xmlreader.Value);
}
Console.Read();
}

Yarattığımız XML File'ını okumak içinde yukarıdaki kodu kullanmamız yeterli.


DataBase'den
veri okuma işlemlerinde sıkça karşılaştığımız DataReader nesnesinin bir benzerini
burada dosya
okumak için kullanıyoruz. Son olarakta, şayet dökümana yeni data girmek isterseniz
aşağıdaki
adımları takip etmeniz yeterli.

public void addXMLFile(string fileName)


{
XmlDocument doc = new XmlDocument();
doc.Load(fileName);
// Eklenecek Element
XmlElement addSicil = doc.CreateElement("SicilNo");
// Elemente Ait Attribute
addSicil.SetAttribute("id","2");

XmlElement addAd = doc.CreateElement("Ad");


// Ad Elementine Ait Değer
addAd.InnerText = "Ali";
// Elementin Parentı Belirtiliyor. Yani SicilNo
addSicil.AppendChild(addAd);

XmlElement addSoyad = doc.CreateElement("Soyad");


addSoyad.InnerText = "Demirci";
addSicil.AppendChild(addSoyad);

XmlElement addTel = doc.CreateElement("Telefon");


addTel.InnerText = "05323254659";
addSicil.AppendChild(addTel);

Boran 45
XmlElement addBolum = doc.CreateElement("Bolum");
addBolum.InnerText = "Bilgi Islem";
addSicil.AppendChild(addBolum);

doc.DocumentElement.AppendChild(addSicil);

XmlTextWriter tw = new XmlTextWriter(fileName,null);


tw.Formatting = Formatting.Indented;
doc.WriteContentTo(tw);
tw.Close();
}

Ş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;

C# ile Sayısal loto tahmini


Önce HTML kodumuzu oluşturmak üzere bir Webform oluşturalım ve aşağıdaki kodu içine yazıp
WebForm1.aspx adıyla kaydedelim.
<%@ Page language="c#" Codebehind="WebForm1.aspx.cs"
AutoEventWireup="false" Inherits="csharptest.WebForm1" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
<HEAD>
<title>Sayısal Loto Tahmini</title>
<meta content="Microsoft Visual Studio 7.0" name="GENERATOR">
<meta content="C#" name="CODE_LANGUAGE">
<meta content="JavaScript" name="vs_defaultClientScript">
<meta content="http://schemas.microsoft.com/intellisense/ie5"
name="vs_targetSchema">
</HEAD>
<body MS_POSITIONING="GridLayout">
<form id="Form1" method="post" runat="server">
<asp:button id="Button1" style="Z-INDEX: 101; LEFT: 12px; POSITION: absolute;
TOP: 153px" runat="server" Text="Yeniden Dene" Width="93px" Height="26px"
Font-Names="Verdana" Font-Size="XX-Small"
ForeColor="Maroon"></asp:button></form>
</body>
</HTML>

Şimdi de bu webformun codebehind dosyası olan "WebForm1.aspx.cs" dosyasını oluşturalım.

string myCheckString = "";


private void Button1_Click(object sender, System.EventArgs e)
{
int Defa = 6;

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.

Şimdi menu elemanlarımıza Properties penceresinden isim verelim. Aşağıda gördüğünüz


pencereden form design penceresinden seçtiğiniz elemanla ilgili özelliklere ulaşabilirsiniz.Şimdi Edit
menu elamanına tıklayarka Properties ekranındaki name özelliğine "menuEdit" yazalım. Burda
menu elemanına verdiğimiz ismi daha sonra kod yazarken kullanacağımız için aklımızda kalacak bir
isim vermemiz düzenli kod yazmak için önemli bir sebeptir. Menu elemanlarıya işimiz bittiğine göre
sıra menuyu kontrol edeceğimiz butonu yerleştirmeye geldi. ToolBox penceresinden "Buton" a çift
tıklayarak forma bir buton yerleştirelim Daha sonra butona tıklayıp Properties pencereisnden buton
ismi (Name) olarak "BizimButon " yazalım. BizimButon' un text özelliğine is "MENU PASİF ET"
yazısını yazalım. Bu yazıyı yazmamızın sebebi is şudur: Menu elemanları varsayılan olarak aktif
durumdadırlar. Bu yüzden menüyu pasif hale getirmek için bu yazıyı seçtik.

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;

Yukarıdaki kodlarla programımızın kullanacağı bir takım sistemler derleyiciye bildiriliyor.

public class Form1 : System.Windows.Forms.Form

System.Windows.Froms.Form sınıfından yeni bir Form1(bizim form) sınıfı türetilierek bu form


içindeki elemanlar tanımlanıyor.

private System.Windows.Forms.MainMenu mainMenu1;


private System.Windows.Forms.MenuItem menuFile;
private System.Windows.Forms.MenuItem menuEdit;
private System.Windows.Forms.MenuItem menuItem3;
private System.Windows.Forms.MenuItem menuItem4;
private System.Windows.Forms.Button BizimButon;
private System.ComponentModel.Container components = null;

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.

static void Main()


{
Application.Run(new Form1());
}

Uygulamamızın Form1 üzerinden gerçekleştirileceğini belirtir.

İşte buda bizim kodumuz :

private void BizimButon_Click(object sender, System.EventArgs e)


{
if (menuEdit.Enabled)
{
menuEdit.Enabled=false;
BizimButon.Text="MENU AKTIF ET";
}
else
{
menuEdit.Enabled=true;
BizimButon.Text="MENU PASIF ET";
}
}

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.

Sayfamızın adı BarChart.aspx.cs


using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;

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);

// canvas color (Resmin Background Rengi)


g.Clear(Color.White);

// title
g.DrawString("Okuma-Yazma",new Font("Thoma",14),
Brushes.Black,new PointF(100,5));

int[] values = new int[2];


values[0] = 3256;
values[1] = 244;
int total = 0;

for(int i=0 ; i<values.Length ; i++)


{
total += values[i];
}

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);

// Renk Tanım Bölümü


PointF xy1 = new PointF(480, 80);
PointF xy2 = new PointF(505, 78);

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);

for(int i=0 ; i<200 ; i+=20)


{
// Grid değerlerini Belirten Rakamlar
g.DrawString(("%"+(200-i)/2),new Font("Arial",8),Brushes.Black,
10,i+60);
// Grid Çizgileri
g.DrawLine(Pens.Black,linePoint1,linePoint2);
linePoint1.Y += 20;
linePoint2.Y += 20;
}

// Grafik Kolonları
int spacebetbars = 120;
int scale = 2;

for(int j=0 ; j<values.Length ; j++)


{
g.FillRectangle(new SolidBrush(getColor(j)),(j*spacebetbars)+80,
270-((values[j]*100/total)*2),80,(((values[j]*100/total))*scale)+5);

g.DrawRectangle(Pens.Black,(j*spacebetbars)+80,
270-((values[j]*100/total)*2),80,(((values[j]*100/total))*scale)+5);

// Barların Altındaki Rakamlar


g.DrawString(values[j].ToString(),new Font("Arial",8),
Brushes.Black,(j*spacebetbars)+110,280);
}

// Resim Yaratılıyor
bm.Save(Response.OutputStream,ImageFormat.Jpeg);
}

private Color getColor(int itemIndex)


{
Color objColor;

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;
}
}

Bitmap bm = new Bitmap(600,300);


satırını kullanarak grafiğimizin boyutlarının 600'e 300 olacağını belirttik.

Graphics g = Graphics.FromImage(bm);
satırı ilede bu bm nesnesi üzerinde çizim yaparken kullanacağımız grafik
nesnesini yarattık.

Şimdide Graphics nesnesine ait örnekte kullandığımız özelliklere bakalım.

.DrawString=Yarattığınız grafik üzerine yazı yazmanızı sağlar.


.DrawRectangle=Grafik üzerine belirtilen ölçülerde dikdörtgen çizer.
.FillRectangle=Grafik üzerine belirtilen ölçülerde dikdörtgen boyar.
.DrawLine=Düz çizgi çizer.

Şimdi gelelim bu grafiği ekrana nasıl basacağımıza. Bunun için yukarıdaki


".cs" dosyasını ".aspx"
dosyası içinde bir resim gibi tanıtıcaz.

Sayfamızın adı GraphicView.aspx

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>

Dilerseniz örneğimizin çıktısına bakalım.

Projenin tamamına ait kodları sitenin "Örnek Kodlar" bölümünde bulabilirsiniz.

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);
}
}
}

Yukarıdaki kodu Notepad editöründe yazıp ToplaComServer.cs


ismiyle kaydedin.

Dikkat ettiyseniz bu uygulamada, standart uygulamalarda olduğu


gibi bir Main() methodu yoktur. C# da yazılan componentler Main()
methodu içermez..

Bu component son derece sade bileşenlerden oluşur. ToplaNS isimli


bir namespace, ToplaClass ismli bir class ve ToplaMethod isimli iki
adet integer tipi parametre alan bir methoda sahiptir.

Komut satırına aşağıdaki satırı girin ve ilgili dizinde


ToplaComServer.dll isimli .Net assembly oluşsun.

csc /t:library
ToplaComServer.cs

COM Client (ToplaComClient.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);
}
}

Yukarıdaki kodu Notepad editöründe yazıp ToplaComClient.cs


ismiyle kaydedin.

İkinci satırdaki using ToplaNS ifadesiyle, erişilmek istenen COM


Server'ın namespace ismini belirtiyoruz.
ToplaClass topobj=new ToplaClass(); ifadesiyle ToplaClass objesinin
topobj isimli bir instance ı oluşturuluyor.
topobj.ToplaMethod(5,10); ifadesiyle topobj objesinin ToplaMethod
methoduna iki adet integer tipinde değer gönderilerek çağırılıyor.

Komut satırına aşağıdaki satırı girin ve ilgili dizinde


ToplaComClient.exe isimli çalıştırılabilir dosya oluşsun.

csc ToplaComClient.cs

Oluşan ToplaComClient.exe isimli dosya çalıştırıldığında ekrana aşağıdaki sonuç gelir.

Toplam: 15

Not: ToplaComClient.exe isimli dosyanın ToplaComServer.dll isimli .Net Componentine


erişebilmesi için iki dosyada aynı dizinde olmak zorundadır veya .Net Framework unun
sunduğu gacutil isimli tool kullanılarak Global Assembly Cache'e oluşturduğumuz .Net
assembly install edilmelidir. Yazar : İzzet Özel (izzetozen@post.com)

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;

Bir önceki .net framework’den bahseden yazımda .net ortamında derleme


işleminin nasıl gerçekleştiğinden bahsetmiştim. Ama yine hızlı bir şekilde
değineceğim. .net ortamında derleme işlemi gerçekleştiginde kaynak kod
Intermediate Language(IL) denilen ara koda dönüştürülür ve daha sonra bu ara
kod (IL) Just in time activation denilen bir işlemle çalıştırılır. Fakat c++ kaynak
kodu derlendiğinde kaynak kod assembly koduna çevrilir ve daha sonra bu
Assembly kodu çalışır.

· Statements

C++ dilinde kullandığımız statmentların mantığında bir değişme olmasada artık


C# da bir değişkenin sıfır ile eşitliğini kontrol ederken eşit (==) veya eşit değil
(!=) operatörlerini kullanmak durumundayız

C++ da legal bir kod

int x ;

if (x) {

// işlemler..
}

while(x){

// işlemler...

yukarıdaki kod C# ‘da error verecektir. C#


verisyonu ise

Boran 58
if (x !=0){

// işlemler...

while (x !=0){

// işlemler...

Bu şekilde bir kod ise c# da legaldir

Aşağıdaki anahtar kelimeler C# ve C++ ‘da aynı şekilde kullanılmaktadır.

for, return, goto, break, continue

· Sınıf tanımlaması ve Deklerasyonu

C++’da main fonkisyonu yani programın çalışmaya başlıyacağı ilk nokta


sınıfın dışında tanımlanır. Fakar C#‘da Main fonksiyonu yine bir sınıfın içinde
tanımlanmalıdır. Bu durumda aklımıza şöyle bir soru gelebilir. Peki programcı
tanımladıgı iki sınıfın içindede farklı Main fonksiyonları tanımlarsa ne olur? Bu
durumda compile aşamasında hagi Main fonksiyonunun önce çalışacağına dair
derleyiciye bir parametre geçmesi gerekir.

int main(){

//işlemler..

return 0;

C++ da legal bir kod

Boran 59
Yukarıdaki kod C#‘da hata verir.

C#‘da bir Main fonksiyonu aşağıdaki gibi tanımlanır.

using System;

class Myclass{

public static void Main(){

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.

Aşağdaki kod C++‘da bir sınıfın veri elemanlarının tanımlanmasını gösterir.

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{

public int x,y;

protected int z;

public void Mymethod(){

public int x,y;

private int z;

internal k;

//...

//...

şeklinde sınıfın veri elemanları ayrı ayrı tanımlanmalıdır.

· “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.

Aşağıdaki C# kodu daha iyi anlamanıza yardımcı olacaktır.

MyClass mine ;

/* Stack’de mine isimli bir referans tanımladım.C++’ daki

initialize edilmemiş bir göstericiye (Pointer’a) bezner bir şekilde */

mine = new MyClass();

/* Myclass isimli sınıfın parametresiz(Default) constructor’ını çağırarak


MyClass’ın heap’de instance’ını oluşturdum.Ve instance’ı yaratılmış nesnenin
başlangıç adresini mine isimli refrans’a atadım. */

New anahtar kelimesini implicit türler içinde kullanmak mümkün.Sonuçta C# da


herşey sınıflardan oluşmuştur.

int x = new int() ;

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.

Esasında bu işlemin temelinde operator overloading fonksiyonlarının static


fonksiyonlar olarak tanımlanması yatmaktadır.Normalde c++ ‘da bir sınıfın +=
operatörünü overload ederken this göstericisinden faydalanılırız. this
göstericisi ise o sınıftan türemis hangi instance’a ait işlem yapıyorsak onun
veri elemanlarına ulaşmamızı sağlar. İşte sorun tam bu noktadan
kaynaklanmaktadır. Yani C# da overload edilen operatörlerin static
tanımlanmasından kaynaklanmaktadır. Bu durumda o instance ın this
göstericisine ulaşmak mümkün olmamaktadır.Çünkü static fonksiyonlar c++
daki global fonksiyonlar gibi davranırlar. Bu yüzden sistem bu işlemi bizim
yerimize gerçekleştirmektedir.

Bir örnek vermek istiyorum

using System;

namespace OOverloading

class Vector

public double x, y, z;

public Vector(double x, double y, double z)

this.x = x;

this.y = y;

Boran 63
this.z = z;

public Vector(Vector rhs)

x = rhs.x;

y = rhs.y;

z = rhs.z;

public override string ToString()

return "( " + x + " , " + y + " , " + z + " )";

public static Vector operator + (Vector lhs,


Vector rhs)

Vector result = new Vector(lhs);

result.x += rhs.x;

result.y += rhs.y;

result.z += rhs.z;

return result;

Boran 64
static void Main()

Vector vect1, vect2, vect3, vect4;

vect1 = new Vector(3.0, 3.0, 1.0);

vect2 = new Vector(2.0, -4.0, -4.0);

vect4 = new Vector(0.0, 0.0, 0.0);

vect3 = vect1 + vect2;

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 )

C# da yanlızca aşağıdaki operatörler overload edilebilirler.

Unary operatörler: +, -, !, ~, ++, --, true, false

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.

Bu yazıda yeni başlayanlar için faydalı olacağını umduğum,bu temel


bileşenler ve bu
bileşenlerin sıkça kullanılan özellik ve metodlarını içeren bir örnek
yapacağız...

Kodlamamızı Visual Studio.Net yada Web Matrix'te yazabiliriz.Ben


bu örneği Visual Studio.net
ile yazdım.Öncelikle her iki programda da bulunan ToolBox'ın Web
Forms tabından 9 tane
Button, 2 tane ListBox ve 1'er tane CheckBox, RadioButton, TextBox ve
Label bileşeni
yerleştirelim.

Örneğimiz şu şekilde çalışacak;

TextBox1'e girdiğimiz veri, Ekle butonuna tıklanarak RadioButton1'in


durumu da
kontrol edilerek normal bir biçimde veya büyük harfle ListBox1'e
eklenecek.

ListBox1'deki veri silinebilecek,ListBox2'ye teker teker veya


bütünüyle aktarılabilecek,
seçildiğinde Label1 bileşeninde seçilen indexdeki text değeri
görünecek.

ListBox2'ye aktarılan veri ListBox1'e geri aktarılabilecek, yukarı veya


aşağı yönde
ilerletilebilecek ve xml dosyasına kayıt (System.Xml Namespace'ini
eklemeyi unutmayın)
edilecek.

CheckBox1'in Seçili olduğu duruma göre Label1'in arkaplan rengi


değişecek ve boolean
durumu yine bu bileşende gösterilecek.

private void Page_Load(object sender, System.EventArgs e)


{
/*
Page_Load prosedürü web formumuzun yüklendiği ilk anda
yapılacak İşleri

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;
}

TextBox1'e girilen bilgiyi Listbox1'e ekler.Ekleme İşlemi sırasında


RadioButton1'in durumunu kontrol ederek eğer RadioButton1 işaretli
ise bilgiyi ListBox1'e
büyük harflerle yazar.

private void Button1_Click(object sender, System.EventArgs e)


{
if (RadioButton1.Checked) // RadioButton işaretli ise
{
ListBox1.Items.Add(TextBox1.Text.ToUpper());
// TextBox1'deki Bilgiyi ToUpper() metodu ile büyük harflere
çevirip
// ListBox1'e ekler
}
else
{
ListBox1.Items.Add(TextBox1.Text);

Boran 68
}
TextBox1.Text="";
}

ListBox1'de seçili bir eleman olup olmadığını kontrol eder eğer


seçili eleman var ise veriyi
Listbox2'ye aktarır.

private void Button2_Click(object sender, System.EventArgs e)


{
if (ListBox1.SelectedIndex > -1) // Seçili Eleman varsa
{
ListBox2.Items.Add(ListBox1.Items[ListBox1.SelectedIndex].Text);
ListBox1.Items.Remove(ListBox1.Items[ListBox1.SelectedIndex].Text);
}
}

ListBox2'de seçili bir eleman olup olmadığını "SelectedIndex"


özelliğinden yola çıkarak
kontrol eder eğer seçili eleman var ise veriyi Listbox1'ye aktarır.

private void Button3_Click(object sender, System.EventArgs e)


{
if (ListBox2.SelectedIndex > -1)
{
ListBox1.Items.Add(ListBox2.Items[ListBox2.SelectedIndex].Text);
ListBox2.Items.Remove(ListBox2.Items[ListBox2.SelectedIndex].Text);
// ListBox2.Items[index].text gibi bir ifadede index değeri, bilginin
// liste kutusundaki yerini verir ve bu numaralandırma bütün C#
// işlemlerinde olduğu gibi 1 ile değil 0 ile başlar
}
}

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...

private void Button4_Click(object sender, System.EventArgs e)


{
for (int i = 0 ;i <= ListBox1.Items.Count-1; i++)
ListBox2.Items.Add(ListBox1.Items[i].Text);
ListBox1.Items.Clear(); // ListBox1'in içeriğini temizler
}

Yine For Döngüsünü kullanarak bu sefer ListBox2'deki elemanları


ListBox1'ye ekliyoruz.
Ekleme işlemini ListBox'ın Add() metodunu kullanarak yapıyoruz...

private void Button5_Click(object sender, System.EventArgs e)


{
for (int i = 0 ;i <= ListBox2.Items.Count-1; i++) /* Bu ifade
ListBoxtaki
bütün satırları seçmeyi ifade eder.Count-1 kullanılmasının nedeni
yukarıda da değindiğim gibi değerleri 0'dan başlamasındandır.
*/
ListBox1.Items.Add(ListBox2.Items[i].Text);
ListBox2.Items.Clear();
}

Bu prosedür ile ListBox'ların SelectedIndexChange Event'ini ve


SelectedItem özelliğini

Boran 70
kullanarak, ListBox1'deki seçili metnin Label1'de görünmesini
sağlıyoruz...

private void ListBox1_SelectedIndexChanged(object sender,


System.EventArgs e)
{
Label1.Text="Seçiminiz : " + ListBox1.SelectedItem.Text;
// ListBox'ın Seçili satırındaki metin değerini Label1'e yazar
}

ListBox için Remove() özelliği seçili elemanın listeden çıkarılmasını


sağlar.Bu işlemden
önce hiç bir elemanın seçili olmayacağını durumu da hesaba katıp
(Compiler) derleyicimizin
hata vermemesi için seçili elemanın varlığını kontrol ediyoruz...

private void Button6_Click(object sender, System.EventArgs e)


{
// Bu prosedür seçili elemanın olup olmadığını kontrol eder, eğer seçili
// eleman varsa ListBox'tan çıkarır
if (ListBox1.SelectedIndex > -1)
{
ListBox1.Items.Remove(ListBox1.Items[ListBox1.SelectedIndex].Text);
}
}

Bu prosedür diskimizde myxmldoc.xml isimli bir Xml dosyası


yaratarak ListBox2'deki satırları
bu xml dosyasında oluşturduğumuz "Kişi" alanına
eklemektedir.Xml dosyasına yazma işlemini
kullanmak için programınıza System.Xml namespace'ini eklemeniz
gerekmektedir...

private void Button7_Click(object sender, System.EventArgs e)


{
XmlTextWriter myxmlWrtr =new
XmlTextWriter("d:\\myxmldoc.xml", null);
// Yeni xml dosyası oluşturuyoruz
myxmlWrtr.WriteStartDocument();
// Xml Dosyasına yazmaya başlıyoruz
myxmlWrtr.WriteComment("ListBox2'deki verileri Xml Dosyasına
Yazma İşlemi");

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();
}

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.

private void Button8_Click(object sender, System.EventArgs e)


{
String a;
if (ListBox2.SelectedIndex-1 > -1)
{
a = ListBox2.Items[ListBox2.SelectedIndex-1].Text;
ListBox2.Items[ListBox2.SelectedIndex - 1].Text =
ListBox2.Items[ListBox2.SelectedIndex].Text;
ListBox2.Items[ListBox2.SelectedIndex].Text= a ;
}
}

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.

private void Button9_Click(object sender, System.EventArgs e)


{
String a;

if (ListBox2.SelectedIndex+1 < ListBox2.Items.Count )


{
a = ListBox2.Items[ListBox2.SelectedIndex+1].Text;
ListBox2.Items[ListBox2.SelectedIndex + 1].Text =
ListBox2.Items[ListBox2.SelectedIndex].Text;
ListBox2.Items[ListBox2.SelectedIndex].Text= a ;
}
}

"Label1'i Renklendir" CheckBox'ı hemen altında bulunan Label1'e


kendi durumunu yazdırmak ve
arka plan rengi vermek ve için kullanılmaktadır.Form ilk
yüklendiğinde default olarak CheckBox
işaretsiz gelir fakat CheckBox'ın durumu ve istediği renk Label1'e
uygulanmaz.Bunun sebebi
sayfanın ilk yüklendiği ânı ifade eden Page_Load prosedürde bu
durumla ilgili komut olmamasıdır.

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;
}
}

private void RadioButton1_CheckedChanged(object sender,


System.EventArgs e)
{
if (RadioButton1.Checked) // RadioButton işaretli ise
TextBox1'deki değer
// büyük harflere dönüştürülecek
{
TextBox1.Text.ToUpper();
}
}

Örneğimiz ilk çalışma anında MSIL koduna dönüştürüleceğinden


biraz geç
yüklenecektir ama sonraki yüklemeler yine MSIL denilen Assembly
koddan dolayı
son derece hızlı yüklenecek.

Umarım örneğim yararlı olmuştur, Bir sonraki yazıda görüşme


üzere...

Sorularınız için mtb@mustafaozlu.com adresine mail atabilirsiniz..

Mustafa ÖZLÜ

Bu makalede yer alan örneğin kodu için tıklayın


http://www.aspnedir.com/ornekkod.asp?id=111

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.

MSIL'e Genel Bakış


MSIL yani Microsoft Intermediate Language bir ara dildir, yazmış olduğunuz kodlar ilk
defa derleme anında bu ara dile dönüştürülür. MSIL CPU'dan bağımsızdır ve stack-tabanlı
bir bilgi olduğu için rahatlıkla bulunduğu platforma özel native koda dönüştürülebilir.
MSIL yorumlanmaz(interpret), derlenir(compile). Varolan Just-In-Time(JIT) derleyici ara
dil kodunu native koda dönüştüren bir görev üstlenir. Bu stack tabanlı kod sayesinde
farklı platformlar arası taşınabilme özelliği ortaya çıkmaktadır. Biraz kafanız karışabilir
ama zaten bu makale de bu işlemlerin nasıl olduğunu, arka planda neler yapıldığını ve ara
dil kodunda neler olduğunu anlayabilmemiz için yazıldı.

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:

Console.WriteLine ("Merhaba Dunya")

Az sonra anlatacağımız Ildasm aracı ile oluşacak ara dil kodunu açacak olursak:

// ildasm aracı ile dissamble edilmiş kod


ldstr "Merhaba Dunya"
call void
[mscorlib]System.Console::WriteLine(string)

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);

Ildasm aracı ile dissamble ettiğimizde karşımıza gelecek kaynak kodu:

// ildasm aracı ile dissamble edilmiş kod


IL_0000: ldc.i4.s 10
IL_0002: stloc.0
IL_0003: ldloc.0
IL_0004: ldc.i4.s 20
IL_0006: beq.s IL_000d
IL_0008: ldloc.0
IL_0009: ldc.i4.s 20
IL_000b: mul
IL_000c: stloc.0
IL_000d: ldloc.0
IL_000e: call void
[mscorlib]System.Console::WriteLine(int32)

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.

ldloc.0 i değişkenini stack'e ekler.

ldc.i4.s integer sabiti 0'ı stack'e ekler.

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.

ldloc.0 elimizdeki i değişkenin içeriğini stack içerisine yazar.

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.

ILDASM ile Hata Ayıklama


Microsoft .NET Framework SDK içerisinden bir disassembler aracı da çıkmaktadır.
Disassembler dediğimiz varolan assembly'lerin içeriğini ortaya çıkarmasından
gelmektedir. Bu IL disassembler'ın adı Ildasm.exe 'dir. Konum olarak
[Sürücünüz]\Program Files\Microsoft.Net\FrameworkSDK\Bin klasörünün altındadır.
Ildasm assembly dediğimiz .NET nesnelerini yükleyerek, MSIL kodunu ve diğer bilgileri
bize göstermektedir.

Örnek Ekran Görüntüsü:

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.

Kaynak : www.aspnedir.com adresinden alinmiştir.

Boran 79

You might also like