Her ne kadar bu bölüm kitabın 3. bölümü olsa bile nesneye yönelik programcılık konusunda henüz yolun başında olanları düşünerek bölümün ilk birkaç sayfasında teorik açıklamalardan kaçınarak Class’lardan namespace’lerden, metotlardan kısaca söz edilecektir. Bu kitabı ilk kaleme aldığımda ilk 2 bölüm şimdikinden daha yüzeysel veya daha az teknikti. Özellikle 2. bölümde yani kitabın hemen başında teknik konulardan hafiften söz etmeye karar verince anlatılanların bazı okurlar tarafından ilk okumada anlaşılmama ihtimali belirdi. Bu nedenle bu bölümün baş tarafını yeniden kaleme alıp küçük eklemeler yaparak okurları anlatılacaklara hazırlamayı tercih ettik.
Visual Studio’nun veya C# için hazırlanmış Express Edition’ın görsel imkanlarından yararlanmadan kod yazmak istiyorsanız Not Defteri ile C# kodunuzu yazıp .NET Framework ile birlikte gelen C# derleyicisi ile derleme yapabilirsiniz. Bilgisayarınızda .NET Framework kurulu olduğuna göre C# derleyicisi zaten vardır. Başka bir deyişle C# uygulamaları geliştirmek için Visual Studio’yu kullanmak zorunda değilsiniz.
Yazdığınız C# kodunu derleyip EXE dosya hazırlayan program dosyasının(CSC.EXE) yerini aşağıda görebilirsiniz. Kullandığınız bilgisayara .NET Framework’ün farklı bir sürümü yüklüyse bu dosya başka bir klasörde olabilir. Kullandığınız bilgisayara Visual Studio 2005’i veya .NET Framework 2.0’ı kurduğunuzda Windows’un kurulu olduğu klasörün altında .NET Framework 1.1 ve 2.0’a ait dosyalar olmaktadır. Visual Studio 2008’i kurduğunuzda ise ayrıca .NET Framework 3.0 ve 3.5 sürümleri kullanılabilir durumda olmaktadır.

Hazırlayacağınız CS uzantılı kod dosyalarını CSC.EXE dosyasının bulunduğu klasöre kaydetmeli veya Windows’un Sistem Özellikleri diyalog kutusunda Gelişmiş sekmesindeki Sistem Değişkenleri seçeneğinden yararlanıp ayarlama yapmalısınız. Path seçeneğinin içeriğine aşağıda verilen satırlardan birisini ekleyip bilgisayarı yeniden başlatırsanız hangi klasörde olursanız olun CS uzantılı kod dosyalarını derleyebilirsiniz.
Visual Studio’dan yararlanmadan Not Defteri veya başka bir editörle hazırladığınız C# programlarında .NET Framework 3.5 ile gelen sınıfları kullanıyorsanız arama yoluna .NET Framework 3.5’a ait klasörü dahil etmelisiniz.
"C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727;"
“C:\WINDOWS\Microsoft.NET\Framework\v3.5;”
Daha sonra değinileceği üzere yukarıda sözü edilen derleyiciden başka .NET Framework 3.x/2.0 SDK(Software Development Kit) adı altından çok sayıda yardımcı program verilmektedir. Bu programlardan yararlanmayı düşünüyorsanız Visual Studio’nun kurulu olduğu klasörün altındaki “.SDK\v.2.0\Bin” klasörünü de arama yoluna dahil etmelisiniz.
Diğer yandan Başlat menüsünden Visual Studio 2008 Command Prompt komutu verilerek açılan DOS penceresinde Path ayarlaması yapılmasa bile C# kodunuzu istediğiniz yerde derleyebilirsiniz. C# derleyicisinin kullanım şekli ve parametreleri hakkında bilgi edinmek istiyorsanız DOS penceresinde “CSC /?” yazıp enter tuşuna basabilirsiniz.
C# derleyicisi ile C# programlarının nasıl derlenip çalıştırıldığını anlatmak için Not Defteri ile aşağıda verilen satırları yazdık. C# kodunu Not Defteri penceresine yazdıktan sonra “ilk.cs” adıyla kaydettik. Not Defteri ile hazırladığınız C# kodunu CS uzantılı bir dosyaya kaydetmek bir mecburiyet olmasa bile “CS” uzantısını kullanmanız önerilir.

C# tamamıyla nesne yönelimli bir dil olduğu için en az satıra sahip C# programları bile en azından bir Class’a sahip olmak zorundadır. Yukarıda verilen kısa program “sinifim” adında bir Class’a sahiptir. Sınıflarda metotlar, alanlar, olaylar ve özellikler vs. bulunabilmektedir. “Sinifim” adı verilen bu class Main() adında bir metoda sahiptir.
C# programları Main() metoduna sahip olmak zorundadır. Çünkü C# programları çalışmaya Main() metodundan başlarlar. Proje veya uygulamanızda birden fazla sınıf varsa Main() metodunun hangi sınıfta olduğu önemli değildir. Ayrıca Main() metodu static olmalıdır. Bu örnekte Main() metodu geriye değer göndermediği için void olarak işaret ettik. Static nedir, void nedir gibi sorularla şimdilik ilgilenmenizi önermiyoruz.
Bu şekilde hazırlanan C# programı DOS penceresinde derlenip çalıştırılırsa belirtilen bilgi Console sınıfının Write() metodu sayesinde Consol adı verilen DOS ekranına yazılır. Console sınıfından önce yazılan System bir Namespace’tir. Namespace’lerde sınıflar olmaktadır. Tabii bir namespace’in içinde başka namespace’ler olabilir. Bir sonraki satırda kullanılan ReadLine() metodu sayesinde Enter tuşuna basılıncaya kadar program çalışmaya devam eder. ReadLine() yerine Console sınıfının ReadKey() metodunu kullansaydık programın çalışması herhangi bir tuşa basılınca sona ererdi.
WriteLine() metodu kendisine parametre olarak verilen bilgiyi konsola yani DOS penceresine yazdıktan sonra imleci bir sonraki satırın başına almaktadır. Write() metodu ise WriteLine() metodundan farklı olarak imleci bir sonraki satırın başına almaz.
Şimdi sıra geldi bu programı derlemeye. Bu amaçla bir DOS penceresi açılıp komut satırına “CSC ilk.cs” yazılıp enter tuşuna basılınca C# programı derlenmeye başlanır. Yazdığımız programda herhangi bir hata olmadığı için sorunsuzca derlendi.

Bu şekilde yapılan derleme sonucu CS uzantılı kod dosyası ile aynı ada sahip bir EXE dosya hazırlanır. Derleme sırasında CS dosyasından farklı bir ada sahip EXE dosya hazırlamak istiyorsanız out parametresi ile EXE dosyanın adını işaret etmeniz gerekir. Aşağıdaki gibi bir derleme yapılırsa “ilk.cs” dosyasının derlenmiş haline “siftah.exe” adı verilir.

.NET uyumlu programlama dilleri için hazırlanmış sınıflar namespace adı verilen yapılarda saklanmaktadır. C# programı dahilinde kullanmak istediğiniz sınıf .NET Framework ile gelen hangi namespace’te yer alıyorsa o namespace’deki sınıfları kullanmak istediğinizi using deyimi ile belirtmeniz gerekir veya yukarıda yapıldığı her seferinde sınıf adının önüne ilgili namespace’in adını yazmalısınız.
Consolesınıfı System adlı namespace’te yer aldığı için her iki satırın başına “System” yazdık. Söz konusu namespace’i kod dosyası dahilinde çok kez kullanıyorsanız her seferinde namespace’in adını yazmak yerine aşağıda yapıldığı gibi ilgili namespace’deki sınıfları kullanmak istediğinizi using deyimi ile belirtmeniz önerilir.

C# programları dahilinde .NET Framework ile gelen namespace’lerdeki sınıfları kullanmanın dışında kendi hazırladığınız class’ları bir namespace’in içine koymanız gerekir. Yukarıda bunu yapmamış olmamıza rağmen herhangi bir hata meydana gelmedi. Çünkü programcı hazırladığı Class’ları bir namespace’e yerleştirmediği zaman derleyici bir namespace hazırlıyor. Şimdi yukarıda verilen programdaki Class’ı bir namespace’e dahil edeceğiz.

Bir namepace’e istediğiniz sayıda Class’ı dahil ederek gruplayabilirsiniz. Henüz yolun başında olan birisinin sınıflarını gruplamak için namespace hazırlamak gibi bir sorunu olmayacağına göre namespace kavramı hakkında az da olsa bilgi sahibi olduğunuzda .NET Framework ile gelen sınıflar hakkında daha kolay bilgi edinme ve kullanma şansı elde edersiniz.
Statik Olan ve Olmayan Metotlar
Şimdiye kadar C# hakkında anlatılanlardan şu sonucu çıkarmış olmalısınız: En küçük C# uygulamasını bile Class olarak düzenlemek gerekmektedir. Örneğin yukarıda verilen kodda “sinifim” adında bir class hazırlayıp bu Class’ın “Deneme” adını verdiğimiz namespace’e konulmasını sağladık. Ardından bu Class dahilinde hazırladığımız Main() metodunda Console sınıfının Write() ve ReadLine() statik metotlarını kullandık. Statik olmayan metotlar nasıl kullanılır sorusuna cevap verebilmek için aşağıda verilen kodu hazırladık.
using System;
class Deneme
{
static void Main()
{
Console.Write("Karekökü alınacak sayıyı girin : ");
string str = Console.ReadLine();
int sayi = Convert.ToInt32(str);
double karekok = System.Math.Sqrt(sayi);
Console.Write("Sayının Karekökü : ");
Console.Write(karekok);
}
}
Bu kodun üzerinde durup biraz konuşmamız gerekecek. İlk olarak Console sınıfının statik Write() metodu ile kullanıcıya mesaj verip karekökü alınacak sayıyı konsola yazmasını istedik. Devamında kullanıcının girdiği sayıyı yani Enter tuşuna basana kadar konsola yazdıklarını “str” adı verilen değişkene aktardık. Kullanıcının konsola yazdıklarını string tipindeki değişkene aktarırken Console sınıfının statik ReadLine() metodundan yararlandık. Devamında aşağıda verilen satır ile kullanıcının konsola yazdığı bilgiyi Convert sınıfının ToInt32() metodu ile int tipine dönüştürüp “sayi” adı verilen değişkene aktardık.
sayi = Convert.ToInt32(str);
Tabi kullanıcı int tipindeki değişkene aktarılamayacak bilgiyi konsola yazarsa dönüştürme sırasında hata meydana gelir ve programın çalışması kırılır. Kodun devamında bu int tipindeki değişkenin içeriğini .NET Framework ile gelen Math sınıfının Sqrt() metodu ile karekökünü alıp “karekok” adını verdiğimiz double tipindeki değişkene aktardık.
Kısaca anlatmak gerekirse konu statik metotlar olduğunda kullanmak için herhangi bir hazırlık yapmak gerekmiyor. Statik olan ve olmayan metotların arasındaki farkı ortaya çıkarmak için aşağıdaki gibi 2 class’a sahip bir konsol uygulaması hazırladık.
namespace Deneme
{
class sinif_1
{
static void Main()
{
}
}
class sinif_2
{
public static int kare(int number)
{
return number * number;
}
}
}
Bu kodda dikkatinizi “sinif_2” adı verilen class’taki kare() metoduna çekmek istiyoruz. Bu metotta ilk fark etmenizi isteğimiz ayrıntı, bu metodun static olmasıdır. Devamında metodun geriye int tipte bilgi göndermesidir. Şimdiye kadar kullandığımız metotlar geriye bilgi göndermedikleri için void metotlardı. Hazırladığınız metot dışarıdan bilgi alacaksa metot adından sonra parantezin içinde değişken tanımlar gibi parametre hazırlamanız gerekir. “kare” adını verdiğimiz bu metot dışarıdan int tipinde bir bilgi aldığı için int tipinde bir parametreye sahip olmasını sağladık. Bu parametreye “number” adını verdik.
C#’ta metotlardan geriye bilgi gönderme işlemi return anahtar kelimesi ile yapılmaktadır. Bu metotla istenen sayının karesini bulmak istediğimiz için parametreyi kendisi ile çarpıp geriye gönderdik. Şimdi sırada bu metottan yararlanmak var. Bu amaçla Main() metodunu aşağıdaki gibi düzenleyerek kare() adını verdiğimiz metodu kullandık.
static void Main()
{
Console.Write("Karesi alınacak sayıyı girin : ");
string str = Console.ReadLine();
int sayi = Convert.ToInt16(str);
int karesi = sinif_2.kare(sayi);
Console.Write("Sayının Karesi : ");
Console.Write(karesi);
}
Hangi sınıfın hangi statik metodu kullanılmak isteniyorsa önce sınıfın adı sonra metodun adı yazılmalıdır. Şimdi yukarıda hazırlayıp “kare” adını verdiğimiz metodun normal metot olmasını sağlayacağız. Yani metot adından önce yazdığımız static kelimesini sileceğiz.
public int kare(int number)
{
return number * number;
}
Bu andan itibaren bu metot yukarıdaki gibi kullanılamaz. kare() adı verilen bu metodu kullanabilmek için önce sınıfın örneğini almak, başka bir deyişle ilgili sınıftan yola çıkıp nesne hazırlamak gerekir. “Sinif_2” adlı class’ın örneğinin nasıl aldığını aşağıda görebilirsiniz.
class sinif_1
{
static void Main()
{
sinif_2 nesne;
nesne = new sinif_2();
}
}
Main() metodu içinde önce “sinif_2” tipinde bir değişken tanımladık. Devamında new anahtar kelimesi ile bu sınıfın örneğini alıp(yani nesne hazırladık) tanımladığımız değişkene aktardık. Bu andan itibaren sinif_2’den yola çıkarak hazırladığımız nesnenin kare() adlı metodunu kullanabiliriz.
static void Main()
{
sinif_2 nesne;
nesne = new sinif_2();
Console.Write("karesi Alınacak sayı :");
string str = Console.ReadLine();
int sayi = Convert.ToInt16(str);
int karesi = nesne.kare(sayi);
Console.Write("sayının karesi :");
Console.Write(karesi);
}
Bu kodda kare() metodunu işletirken karesini almak istediğimiz sayıyı parantezlerin arasına yazdık. C#’ta metotların sonuna mutlaka “()” parantez eklenir. kare() metodu herhangi bir parametreye sahip olmasaydı bile metot adına parantez eklemek gerekirdi. Bu açıklamadan sonra dikkatinizi sınıftan yola çıkıp nesne hazırladığımız 2 satıra çekmek istiyoruz.
sinif_2 nesne;
nesne = new sinif_2();
Her ne kadar bu 2 satırı bir tek satırda birleştirmek mümkün olsa bile asıl işaret etmek istediğimiz new anahtar kelimesinin kullanıldığı satırda sınıf adına eklenen parantezlerdir. “sinif_2” adında bir sınıfımız olsa bile burada sonuna “()” parantez eklenen bir sınıf olmayıp bir metottur. Programcılar tarafından hazırlanan sınıfların sınıfla aynı ada sahip bir metodu genellikle bulunmakta ve bu metoda yapıcı metot(constructor) adı verilmektedir. Bu metotlar sınıftan yola çıkıp nesne hazırlanmak istendiği zaman kullanılmaktadır.
Dikkat ettiyseniz yukarıda “sinif_2” için böyle bir metot hazırlamadık. Programcı kendi sınıfı içinde sınıfla aynı ada sahip metot hazırlamadığı zaman C# derleyicisi bunu otomatik olarak hazırlamaktadır. Şimdi yukarıda verdiğimiz sinif_2 adlı class’ın yapıcı metoda sahip olmasını sağlayacağız. Bu şartlarda yani herhangi işletilebilir bir satıra sahip olmayan bu metodun varlığı ile yokluğu arasında bir fark yoktur.
class sinif_2
{
public int kare(int number)
{
return number * number;
}
public sinif_2()
{
}
}
Birden Fazla Main() Metodu Hazırlamak
Uygulamanızda birden fazla sınıf varsa Main() metodunun hangi sınıfta olduğunun önemi yoktur. Çünkü C# derleyicisi Main() metodunun hangi sınıfta olduğunu arayıp bulur. Uygulamanızdaki birden fazla sınıfta Main() metodu varsa hangisinin kullanılacağını belirtmeniz gerekir. Bu konuyu anlatmak için aşağıdaki gibi bir konsol uygulaması hazırladık.

Bu şekilde hazırlanan uygulama bilinen şekilde derlendiğinde hata meydana gelir. Çünkü derleme satırında hangi sınıftaki Main() metodunun kullanılmak istendiği belirtilmelidir. Bu kod aşağıdaki gibi derlenirse uygulama ilk sınıftaki Main’den itibaren çalışmaya başlar.

Tabii birden fazla Main() metoduna sahip uygulamada başlangıç noktası olarak seçilmeyen 2. Main() metodu hem public hem de static olduğu için aşağıdaki yapıldığı gibi işletilebilir.
using System;
class ilk_sinif
{
public static void Main()
{
Console.WriteLine("ilk sınıfın Main metodu işletildi");
ikinci_sinif.Main();
Console.Read();
}
}
class ikinci_sinif
{
public static void Main()
{
Console.WriteLine("2. sınıfın Main metodu işletildi");
}
}
Visual Studio ile Windows Forms Application şablonunu kullanarak hazırladığınız projede birden fazla sınıfta Main() metodu varsa hangisinin projenin başlangıç noktası olacağını Project menüsünden komut verilerek ekrana getirilen Project Properties penceresinde seçebilirsiniz. Aynı Class içinde birden fazla Main() metodu hazırlamak istiyorsanız parametre yapılarının farklı olması gerekir.
Write() ve WriteLine() Metotları
Console sınıfının WriteLine() metodu kendisine parametre olarak verilen bilgiyi konsola yazdıktan sonra imleci bir sonraki satırın başına almaktadır. Write() metodu ise WriteLine() metodundan farklı olarak imleci bir sonraki satırın başına almaz. Yukarıda verilen örneklerde konsola yalnızca bir bilgi yazdık. Şimdi konunun anlaşılmasına katkı için konsola 4 bilgiyi arka arkaya yazacağız.
using System;
class sinifim
{
public static void Main()
{
Console.Write("Fenerbahçe");
Console.Write("Galatasaray");
Console.Write("Beşiktaş");
Console.Write("Trabzonspor");
Console.Read();
}
}
Bu kodda Write() metodu ile konsola 4 bilgi arka arkaya yazılmakta ve Read() metodu ile programın işletimi bir tuşa basılıncaya kadar askıya alınmaktadır. Write() metodu ile konsola bilgi yazıldıktan sonra imleç yazma işleminin tamamlandığı yerde bekleyeceği için bu program derlenip çalıştırılırsa aşağıdaki gibi bir sonuç elde edilir.

Bu bilgilerin ayrı satırlara yazılmasını sağlamak için Write() yerine WriteLine() metodunu kullanabilirsiniz. Write() metodu ile konsola yazılan metnin sonuna satır başı karakterini(“\n”) ekleyerek aynı sonucu alabilirsiniz. Satır başı karakterinin nasıl kullanıldığını aşağıda görebilirsiniz.
public static void Main()
{
Console.Write("Fenerbahçe\n");
Console.Write("Galatasaray\n");
Console.Write("Beşiktaş\n");
Console.Write("Trabzonspor\n");
Console.Read();
}
Console sınıfının Read() metodu kullanıcının konsola gireceği bilgileri programa veya bir değişkene aktarılırken işlevsel olmaktadır. Bu örnekte kullanıcının bilgi girmesini istemediğimiz için Read() metodundan önce herhangi bir değişken adı yazmadık. Bu durumda Read() metodu yerine ReadKey() metodu kullanılabilirdi. Şimdi bu örnekte değişiklik yapıp bir değişken tanımlayıp çalışma anında bu değişkene konsoldan bilgi aktarmaya çalışacağız.
class sinifim
{
public static void Main()
{
System.Console.Write("Hangi Yıldayız : ");
int yil = System.Console.Read();
}
}
Bu şekilde değiştirilen uygulamada Write() metodu ile kullanıcıya mesaj verildikten sonra kullanıcının konsola yazacağı bilgiyi Read() metodu ile okuyup “yil” değişkenine aktardık. Aşağıda verilen ekran görüntüsü bu programı derlenip çalıştırıldıktan sonra alındı.

Konsola mesaj yazarken Write() yerine WriteLine() metodunu kullansaydık imleç bilgi girişi için bir sonraki satırda beklerdi. Şimdi bu koda ekleme yapıp kullanıcıdan istenip int tipindeki “yıl” adlı değişkene aktarılan bilgiyi WriteLine() metodu ile ekrana yazacağız.
using System;
class sinifim
{
public static void Main()
{
System.Console.Write("Hangi Yıldayız : ");
int yil = System.Console.Read();
Console.WriteLine();
Console.Write("Girdiğiniz Yıl :");
Console.WriteLine(yil);
}
}
Bu şekilde düzenlenen kod derlenirken hata vermediği gibi çalıştırıldığında da hata meydana gelmez ama konsola yazılan yıl bilgisi ile sonradan Write() metodu ile ekrana yazılan yıl bilgisi birbirinden farklı olur. Aşağıda verilen ekran görüntüsünü bu C# programını derleyip çalıştırdıktan sonra aldık.

Konsoldan okuma Read() metodu ile yapılmaktadır. Read() metodu konsoldan okuma yaparken girilen bilginin ilk karakterinin ASCII kodunu geriye göndermektedir. Bu program çalıştırılıp “Hangi Yıldayız :” sorusuna “A” ile cevap verilirse ekrana 65 yazılır.

Console sınıfının ReadLine() metodu ise farklı şekilde çalışmakta ve konsoldan okuduğu bilginin String tipte olduğunu varsaymaktadır. Bu nedenle yukarıda verilen kodu değiştirip okuma işlemini Read() yerine ReadLine() metodu ile yapmaya çalıştık.
class Deneme
{
static void Main(string[] args)
{
System.Console.Write("Hangi Yıldayız : ");
int yil = System.Console.ReadLine();
System.Console.Write("Girdiğiniz Yıl :");
System.Console.WriteLine(yil);
}
}
Bu şekilde değiştirdiğimiz C# programını derleyip çalıştırırsak hata meydana gelir. Çünkü ReadLine() metodu tarafından okunup geriye gönderilen bilgi string tipte olmasına rağmen burada int tipindeki değişkene aktarmaya çalışıyoruz. Bu hatanın önüne geçmek için “str” adında ve string tipte bir değişken tanımlayıp kullandık.
class Deneme
{
static void Main()
{
System.Console.Write("Hangi Yıldayız : ");
string str = System.Console.ReadLine();
System.Console.Write("Girdiğiniz Yıl :");
System.Console.WriteLine(str);
}
}
Bu hali ile programımız istediğimiz sonucu verir. Bu örnekte konsoldan girilen “yıl” bilgisi matematiksel işlemlerde kullanılmadığı için rakamlardan meydana gelse bile karaktersel bilgi olarak değerlendirmenin bir sakıncası olmaz.
Şimdi bu örnekte değişiklik yapıp kullanıcıdan 2 sayı isteyip bunları birbirleri ile çarptıktan sonra bulunan sonucu konsola yazacağız. Bu amaçla 2 string değişken tanımlayıp ReadLine() ile okunan bilgileri bu değişkenlere aktardık.
class Deneme
{
static void Main()
{
string str1, str2;
System.Console.Write("İlk sayıyı girin : ");
str1 = System.Console.ReadLine();
System.Console.Write("İkinci sayıyı girin: ");
str2 = System.Console.ReadLine();
}
}
Bu program bu hali ile derlenip çalıştırılırsa konsoldan girilen bilgiler string değişkenlere aktarılır. Bu örnekte amacımız kullanıcının sayısal bilgi girmesini ve bu sayıları birbiri ile çarpıp sonucu konsola yazmak olduğu için çarpma işlemi öncesi String değişkenlerin içeriğini dönüştürüp int tipindeki değişkenlere aktarmak gerekir. Bu nedenle bu koda ekleme yapıp int tipinde 2 değişken tanımladık. Ardından string değişkenlerin içeriklerini dönüştürüp int tipindeki değişkenlere aktardık.
static void Main()
{
string str1, str2;
int sayi1, sayi2;
System.Console.Write("İlk sayıyı girin : ");
str1 = System.Console.ReadLine();
System.Console.Write("İkinci sayıyı girin: ");
str2 = System.Console.ReadLine();
sayi1 = System.Int16.Parse(str1);
sayi2 = System.Int16.Parse(str2);
}
Bu kodda sizin için yeni olan System’de yer alan Int16 sınıfıdır. Int16 aslında bir sınıf olmayıp bir struct yani bir yapıdır. Bazen alışkanlıktan struct yerine Class denilmektedir. Bu kitabın ileriki sayfalarında struct’lar hakkında bilgi verilecektir. .NET Framework ile birlikte gelen Int16 gibi yapıları kullanmak sınıfları kullanmaktan pek farklı olmadığı için Int16’nın sınıf mı yoksa yapı mı olduğu ile ilgilenmeyebilirsiniz.
String bilgiyi int tipindeki değişkene aktarırken Int16 yapısının Parse() metodunu kullanabilirsiniz. Dönüştürme yaparken Int16 yerine Int32 yapısının Parse() metodunu kullanabilirdik. Bu örnekte kullanıcıya sayı girin mesajı verilmiş olunsa bile kullanıcı karaktersel bilgi girerse Parse() metodu dönüştürme yapamayacağı için hata meydana gelir.
Bu şekilde konsoldan girilen bilgileri Parse() metodu ile dönüştürüp int tipindeki değişkenlere aktardıktan sonra matematiksel işlem yapabiliriz. Matematiksel işlem sonucu bulunacak değeri aktarmak üzere int tipinde 3. bir değişken tanımladık.
class Deneme
{
static void Main()
{
string str1,str2;
int sonuc, sayi1, sayi2;
System.Console.Write("İlk sayıyı girin : ");
str1 = System.Console.ReadLine();
System.Console.Write("İkinci sayıyı girin: ");
str2 = System.Console.ReadLine();
sayi1 = System.Int32.Parse(str1);
sayi2 = System.Int32.Parse(str2);
sonuc = sayi1 * sayi2;
}
}
Bu kısacak kodda int tipindeki değişkenlere alışkanlık gereği “sayi1”, “sayi2” gibi adlar verdik. Bu durumda birilerinin bu değişkenlerin adlarını bizim kitaptan çalmışsın suçlamasına maruz kalmamak için aynı kodun İngilizce değişken adları kullanılmış halini de verdik.
static void Main()
{
string str1,str2;
int netice, number1, number2;
System.Console.Write("İlk sayıyı girin : ");
str1 = System.Console.ReadLine();
System.Console.Write("İkinci sayıyı girin: ");
str2 = System.Console.ReadLine();
number1 = System.Int32.Parse(str1);
number2 = System.Int32.Parse(str2);
netice = number1 * number2;
}
Bu program derlenip çalıştırılıp konsoldan girilen 1. ile 2. sayının çarpımı sonucu elde edilen sayı 2147.483.647’den büyük olursa hata meydana gelir. Ayrıca string bilgileri Int16 yapısının Parse() metodu ile dönüştürmeyi tercih ettiğimiz için konsoldan girilen sayılar 32767’den büyük olmamalı. Int16’nın Parse() metodu yerine Int32 yapısının Parse() metodunu kullansaydık 1. veya 2. sayı 2.147.483.647 gibi bir değer olabilirdi.
Çarpma işlemi sonucu bulunan sonucu WriteLine() metoduyla direk konsola yazmak mümkün olmasına rağmen amacımız bazı konuları anlatmak olduğu için üçüncü bir string değişken tanımlayıp çarpma işlemi sonucu bulunan değeri dönüştürüp bu değişkene aktardık. Bu işlemi nasıl yaptığımızı aşağıda görebilirsiniz.
static void Main()
{
string str1,str2, sonuc_str;
int netice, number1, number2;
System.Console.Write("İlk sayıyı girin : ");
str1 = System.Console.ReadLine();
System.Console.Write("İkinci sayıyı girin: ");
str2 = System.Console.ReadLine();
number1 = System.Int32.Parse(str1);
number2 = System.Int32.Parse(str2);
netice = number1 * number2;
sonuc_str = System.Convert.ToString(netice);
System.Console.WriteLine("Sayıların çarpımı :" + sonuc_str);
System.Console.Write("Devam etmek için enter tuşuna basın");
System.Console.Read();
}
Dikkat ederseniz burada int tipindeki değişkenin içeriğini string değişkene aktarabilmek için Convert sınıfının ToString() metodundan yararlandık. Bu metot ile int tipindeki bilgiyi string bilgiye dönüştürdükten sonra WriteLine() metodu ile konsola yazdık.
Normal şartlarda konsol uygulamalarında Main() metodunun sonuna gelindiğinde uygulamanın çalışması sona erer. Bu nedenle Main() metodunun içinde iken return deyimi kullanıldığında metottan çıkılır ve uygulamanın çalışması sona erer. Bu nedenle aşağıda verilen kodda kullanıcı 2. sayı niyetine konsola 0 yazarsa return ile Main() metodundan çıkılır.
class Deneme
{
static void Main()
{
string str1,str2;
double netice, number1, number2;
System.Console.Write("ilk sayıyı girin : ");
str1 = System.Console.ReadLine();
System.Console.Write("ikinci sayıyı girin: ");
str2 = System.Console.ReadLine();
if (str2=="0")
return;
number1 = System.Double.Parse(str1);
number2 = System.Double.Parse(str2);
netice = number1 / number2;
System.Console.WriteLine("Sonuç : " + netice.ToString());
System.Console.Write("Devam etmek için enter tuşuna basın");
}
}
Main() metodundan çağrılan başka bir metodun içinde iken uygulamanın çalışmasını hemen sonlandırmak istiyorsanız Environment sınıfının Exit() metodunu kullanabilirsiniz. Bu metot hakkında bilgi vermek için yukarıda verilen ve konsola yazılan 2 sayıyı birbirine bölüp sonucu yine konsola yazan uygulamayı aşağıdaki gibi düzenledik.
class Deneme
{
public static string str1,str2;
public static double sonuc, sayi1, sayi2;
static void girisler()
{
System.Console.Write("ilk sayiyi girin : ");
str1 = System.Console.ReadLine();
System.Console.Write("ikinci sayiyi girin: ");
str2 = System.Console.ReadLine();
if (str2=="0")
System.Environment.Exit(0);
}
static void Main()
{
girisler();
sayi1 = System.Double.Parse(str1);
sayi2 = System.Double.Parse(str2);
sonuc = sayi1 / sayi2;
System.Console.WriteLine("Sonuç : " + sonuc.ToString());
System.Console.Write("Devam etmek için enter tuşuna basın");
}
}
Bu kodda str1, str2, sayi1, sayi2 adlarını verdiğimiz değişkenleri hem Main hem de girisler() metodunda kullanabilmek için değişken tanımlama satırlarını Class bloğuna yazdık.
Main() Metodunu Parametreli Kullanmak
Şimdi yukarıda verilen programda değişiklik yapıp Main() metoduna parametre olarak verilen 2 sayıyı toplayıp konsola yazmayı deneyeceğiz. Başka bir deyişle toplanacak sayıları programı çalıştırıp kullanıcıdan istemek yerine kullanıcı toplamak istediği sayıları DOS penceresinde programın adının yanına yazacak.
Program çalıştırıldığında program adının yanına yazılacak bilgiler Main() metodunun parametresi olarak görüleceği için bu metodun adından sonra parantezlerin içine “string[] pars” yazdık. Başka bir deyişle Main() metoduna ait parantezlerin içinde eleman sayısı belli olmayan bir dizi değişken tanımladık.
İlk olarak kullanıcının programı çalıştırmadan önce program adının yanına yazdığı 2 sayıyı elde edip ekrana yazmakla yetineceğiz. Programcılar Main() metodunun String tipteki dizi değişken parametresine genellikle args adını veriyorlar.

Buradaki pars string tipinde bir dizi değişkendir. “pars[0]” ile dizi değişkenin ilk elemanına ve “pars[1]” ile dizi değişkenin 2. elemanına ulaşılmaktadır. Dizi değişkenler hakkında daha sonra bilgi verilecektir. Bu şekilde değiştirilen C# programını derledikten sonra çalıştırma satırında program adının yanına aşağıdaki gibi 2 sayı yazdık.

Bu sırada enter tuşuna basıp programı çalıştırırsanız 150 sayısı ilk parametre olarak değerlendirilip dizi değişkenin ilk elemanına ve 250 ise “pars” adı verilen dizi değişkenin 2. elemanına aktarılır. Aşağıda verilen sonucu bu program çalıştırıldıktan sonra alındı.

Bu örnekte toplanacak sayıları Main() metoduna parametre olarak verdik. Şimdi bu programda değişiklik yapıp toplanacak sayıları önce int tipindeki değişkenlere aktarıp birbirleri ile toplayıp bulunan sonucu konsola yazacağız.
using System;
class Deneme
{
static void Main(string[] pars)
{
int sayi1, sayi2, sonuc;
System.Console.Write("İlk sayı : ");
Console.WriteLine(pars[0]);
System.Console.Write("İkinci sayı : ");
Console.WriteLine(pars[1]);
sayi1 = Convert.ToInt16(pars[0]);
sayi2 = Convert.ToInt16(pars[1]);
sonuc = sayi1 + sayi2;
Console.Write("Sayıların toplamı :");
Console.Write(sonuc);
}
}
Tahmin edeceğiniz gibi burada “pars” adı verilen dizi değişkenin eleman sayısı programa parametre olarak verilen sayıların(veya bilgilerin) sayısına bağlıdır. Bu program çalıştırılırken program adının yanına 2 yerine 1 sayı yazılırsa hata meydana gelir. Çünkü programda dizi değişkenin 2. elemanın içeriği okunmak istenmektedir.
Benzer şekilde program çalıştırılırken program adının yanına karaktersel bilgi yazılırsa hata meydana gelir. Şimdi yukarıda verilen kodda değişiklik yapıp Main() metoduna parametre olarak verilen bilgileri foreach döngüsü ile elde edip içeriklerini ekrana yazacağız. Bu kitabın ileriki sayfalarında foreach döngüleri hakkında bilgi verilecektir.
static void Main(string[] pars)
{
if (pars.Length > 0)
foreach(string par in pars)
{
Console.WriteLine(par);
}
else
Console.WriteLine("Program parametresiz çalıştırıldı");
}
Şimdi bu dizi değişkenin elemanlarının içeriklerini farklı bir teknikle elde edeceğiz. Environment sınıfının GetCommandLineArgs() metodu çalıştırılan program veya C# uygulamasına ait parametreler hakkında geriye bilgi göndermektedir. Bu metottan yararlanıp konsol uygulamasının parametreleri aşağıdaki gibi elde edilebilir.
using System;
class Deneme
{
static void Main()
{
string[] dizi = Environment.GetCommandLineArgs();
int sayi1, sayi2, sonuc;
System.Console.Write("İlk sayı : ");
Console.WriteLine(dizi[1]);
System.Console.Write("İkinci sayı : ");
Console.WriteLine(dizi[2]);
sayi1 = Convert.ToInt16(dizi[1]);
sayi2 = Convert.ToInt16(dizi[2]);
sonuc = sayi1 + sayi2;
Console.Write("Sayıların toplamı :");
Console.Write(sonuc);
}
}
Bu metot çalıştırılan programın adını 1. parametre olarak kabul edip bütün parametreleri string tipte bir dizi değişkene doldurup geriye göndermektedir. Örneğimizde program adından sonra yazılacak 2 sayıyı toplamak istediğimiz için GetCommandLineArgs() metodunun geriye gönderdiği dizi değişkenin 2. ve 3. elemanları ile ilgilendik.
Visual Studio İle Konsol Uygulaması Hazırlamak
Konsol uygulamalarını Not Defteri ile yazmak yerine Visual Studio ile gelen Console Application şablonundan yararlanabilirsiniz. Bu amaçla New Project diyalog kutusunda Console Application şablonunu seçip Name kutusuna uygulamaya vermek istediğiniz adı yazıp OK düğmesini tıklarsanız Visual Studio aşağıdaki gibi bir kod dosyası hazırlar.

Bu cs uzantılı kod dosyası dahilinde hazırlanan namespace’e projenin adı, konsol uygulaması dahilinde hazırlanan cs dosyasına ise “Program.cs” adı verildi. Ayrıca Class’ın adı “Program” olarak seçildi. Solution Explorer penceresinde cs dosyasının adını değiştirirseniz bundan namespace etkilenir.
Visual Studio tarafından hazırlanan konsol uygulamasına toplam 5 referans dahil edilmekte ve bazı namespace’lerdeki sınıfları kullanılabileceğiniz using deyimi ile işaret edilmektedir. Bu şartlarda bu konsol uygulaması çalıştırılırsa bir DOS penceresi açılır ve hemen kapatılır. DOS penceresinde programın işletiminin durması için Main() metoduna birkaç satır yazdık.
static void Main(string[] args)
{
Console.WriteLine("Fenerbahçe");
Console.WriteLine("Beşiktaş");
Console.WriteLine("Galatasaray");
Console.WriteLine("Çıkmak İçin Enter tuşuna basın");
Console.Read();
}
Bu uygulama çalıştırıldığında aşağıdaki gibi sonuçla karşılaşırsınız. Bu sırada Enter tuşuna basılırsa uygulamanın çalışması sona erer ve tekrar Visual Studio penceresine dönersiniz.

Konsol uygulamasının birden fazla sınıfında Main() metodu varsa Project menüsünden komut verip ekrana Project Properties diyalog kutusunu getirip Startup Object seçeneği ile ayarlama yapmak gerekir.
Konsol uygulamasındaki birden fazla kod dosyası ve birden fazla Class olabilir. Örnek olması için bu konsol uygulamasına 2. bir CS dosyası dahil edip bu kod dosyasında bir Class hazırlayacağız. Konsol uygulamasına 2. bir CS dosyası dahil etmek istiyorsanız Project menüsünden komut verip Add New Item diyalog kutusunu ekrana getirmelisiniz.
Uygulamaya boş bir CS dosyası dahil edecekseniz Code File şablonundan yararlanabilirsiniz. Add New Item diyalog kutusunda Class şablonunu seçip Add düğmesini tıklarsanız CS dosyası ile aynı ada sahip bir class kalıbı hazırlanır.

Örnek olması için bu Class’ta basit bir metot hazırlayacağız. Hazırlayacağımız metot kendisine parametre olarak verilen 2 sayıyı çarpıp bulunan sonucu geriye gönderecektir.
namespace ConsoleApplication1
{
class Class1
{
public int Carpim(int x, int y)
{
return x * y;
}
}
}
Buradaki amacımız konsol uygulamalarında metotların nasıl hazırlanıp kullanıldığını anlatmak olduğu için metodun ne yaptığının önemi yoktur. Tabi başka bir yazar “daha önce yayınlanan kitabımda Carpim adında ve 2 sayıyı birbirleri ile çarpan bir metoda yer vermiştim” deyip bizi dava edebilir. Bu ihtimali karşılık bu açıklamayı yapma gereğini duyduk.
Konsol uygulamasına sonradan dahil ettiğimiz kod dosyasındaki Class’ta bu şekilde metot hazırladıktan sonra ilk CS dosyasına geçip Main() metodunu aşağıdaki gibi düzenledik. Class’tan yola çıkarak nesne hazırlama işlemi new anahtar kelimesi ile yapılmaktadır. İleriki sayfalarda bu konuda bilgi verilecektir.

Bu uygulamanın Program adlı sınıfındaki Main() metodunda ilk olarak int ve kendi hazırladığımız sınıf tipinde(Class1) 2 değişken tanımladık. Devamında “Class1” sınıfının örneğini hazırlayıp “Nesne” adını verdiğimiz değişkene aktardık.
Class’tan yararlanıp nesne hazırladıktan sonra Carpim() adını verdiğimiz metodu kullanarak sayıların çarpımını bulup konsola yazdık. Console Application şablonu ile hazırlanan projenin kodlarına dikkatlice baktığınızda DOS penceresinin açılmasına yönelik herhangi bir deyim veya metodun olmadığını görürsünüz. Console Application şablonu ile hazırlanan proje çalıştırıldığında DOS penceresinin açılmasını sağlayan ayarlama Project menüsünden komut verilerek ekrana getirilen Project Properties penceresinde Output type liste kutusunda yapılmaktadır.
Bir önceki bölümden bildiğiniz gibi C# derleyicisi Windows Forms Application şablonu ile hazırlanan projelerde Application sınıfının Run() metodundan yararlanılmaktadır. Application sınıfı, uygulama ile Windows arasındaki mesaj alış verişini sağlamaktadır. Bu nedenle C# veya .NET uyumlu herhangi bir dilde uygulama geliştirmek isteyenlerin Application sınıfı hakkında bilgi edinmeleri gerekmektedir. Tabii Application sınıfından bi haber olup işe yarar programlar yazmak mümkündür. Bu kitapta işin özünü, geri planını anlatmayı tercih ettiğimiz içindir ki Application sınıfı hakkında ayrıntılı bilgi verilmektedir.
Şimdi bu konsol uygulamasına sonradan dahil ediken Class’ta bir Windows formu hazırlayıp ekrana getireceğiz. Application sınıfından yararlanabilmek ve form hazırlayıp ekrana getirebilmek için “System.Windows.Forms” adlı namespace’i içeren referans veya DLL dosyasından projeyi haberdar etmek veya bu referansın Solution Explorer penceresinde listelenmesi gerekmektedir. Başka bir deyişle .NET Framework ile gelen bu referanstan yararlanmak istediğimizi belirtmemiz gerekiyor. Aşağıda verilen ekran görüntüsüne göre konsol uygulamalarına Visual Studio tarafından 6 referans dahil edilmektedir.

Konsol uygulamanızda System.Windows.Forms’deki sınıflardan yararlanmak istiyorsanız Solution Explorer penceresinden yararlanıp Add Reference diyalog kutusunu ekrana getirip System.Windows.Forms.dll referansını uygulamaya dahil etmelisiniz. Referanslardan uygulamayı, dolayısıyla derleyiciyi haberdar etme işlemleri size anlaşılmaz geliyorsa bunu sorun yapmayınız. Çünkü bu kitabın Assembly adlı bölümünde yazılanları okuduğunuzda bu konular sizin için artık anlaşılmaz olmayacaktır.
System.Windows.Forms.dllreferansı uygulamaya dahil edildikten sonra usign deyimiyle namespace’deki sınıfları kullanmak istendiğinizi belirtirseniz Class adlarından önce namespace adını(System.Windows.Forms) yazmak zorunda kalmazsınız.
class Program
{
static void Main(string[] args)
{
MessageBox.Show("Konsol Uygulaması Başlatılacak");
}
}
Şimdi ise konsol uygulaması dahilinde bir form hazırlayıp ekrana getireceğiz. Bu amaçla konsol uygulamasındaki 2. sınıfın “System.Windows.Forms” adlı namespace’te tanımlı olanFormsınıfını miras almasını sağladık. Ayrıca bu CS dosyasında Class ile aynı ada sahip public bir metot hazırlayıp bu metotta formun Text özelliğini ayarladık.

Class ile aynı ada sahip bu metodu hazırlamak zorunda değilsiniz. Class ile aynı ada sahip metotlara Constructur yani Yapıcı metot adı verilmektedir. Bu metotların işlevi hakkında daha sonra bilgi verilecektir. Hazırlamak istediğiniz sınıf, mevcut sınıflardan hangisinin mirasçısı olacaksa o sınıfın adını hazırlamak istediğiniz sınıfın adından sonra yazmalısınız.
Bu uygulamaya sonradan dahil ettiğimiz cs dosyasındaki Class1’i bu şekilde düzenledikten sonra “Program.cs” dosyasına geçip new anahtar kelimesi ile Class1’den yola çıkıp nesne hazırlayıp Application sınıfının Run() metoduna parametre olarak verdik.
static void Main(string[] args)
{
Class1 Form1 = new Class1();
Application.Run(Form1);
}
.NET Framework ile gelen System.Windows.Forms.Form sınıfından yararlanılarak hazırlanan form standart özelliklere sahip olur. Bu kod işletildiğinde ekrana aşağıdaki gibi bir form getirilir ve form kapatılıncaya kadar konsol uygulaması çalışmaya devam eder.

Yukarıda anlatılan şekilde hazırladığınız form nesnesini ekrana getirmek için Application sınıfının Run() metodundan yararlanmak zorunda değilsiniz. Form1’i ekrana getirmek için ShowDialog() metodundan yararlanabilirsiniz.
static void Main(string[] args)
{
Class1 Form1 = new Class1();
Form1.ShowDialog();
}
Konsol uygulamasında bu şekilde form hazırlamak size mantıklı gelmeyebilir ama buradaki amaç deneyseldir. Şimdi ise kod yazarak ListBox hazırlayıp formun üzerine yerleştireceğiz.
static void Main(string[] args)
{
Class1 Form1 = new Class1();
System.Windows.Forms.ListBox Liste1;
Liste1 = new System.Windows.Forms.ListBox();
Liste1.Top = 25;
Liste1.Left = 25;
Liste1.Parent = Form1;
Liste1.Items.Add("Fernando Alonso");
Liste1.Items.Add("Michael Schumacher");
Form1.ShowDialog();
}
Yukarıda konsol uygulamasına 2. bir class dahil etmiş ve bu Class’ın Form class’ının mirasçısı olmasını sağlamıştık. Devamında ise bu class’tan yararlanarak nesne hazırlayıp ekrana getirmiştik. Aslında form nesnesi hazırlamak için ayrıca bir Class hazırlamak zorunda değilsiniz. Konunun açığa çıkması için yukarıda verilen konsol uygulamasındaki 2. cs dosyasını silip ilk dosyayı(program.cs) aşağıdaki gibi düzenledik.
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Form Form1 = new Form();
Form1.ShowDialog();
}
}
}
Konsol Uygulamaları ve Application Sınıfı
Bir önceki bölümde kısaca sözü edilmiş olunsa bile tekrar etmekte fayda vardır: Windows’ta işlemler mesajlar aracılığı ile yapılır. Çalıştırılan her program için bir mesaj kuyruğu hazırlanır. Örneğin kullanıcı formdaki TextBox’a bir harf yazdığında Windows ilgili uygulamanın mesaj kuyruğuna kullanıcının TextBox’ın içinde iken bir tuşa bastığını bir mesaj olarak mesaj kuyruğuna yazar. Uygulama ise kendisine ait mesaj kuyruğundaki mesajı okuyup gereğini yapar. Ne zaman ki projenin ana formu kapatılır o zaman mesaj kuyruğu silinir. Ancak konsol uygulamalarında durum farklıdır ve konsol uygulamaları için mesaj kuyruğu hazırlanmaz. Konsol uygulamaları sürekli konsoldan bir şeyler okuyup konsola yazarlar.
Konsol uygulamalarının bazı özelliklerinden söz etmek için Visual Studio ile yeni bir konsol uygulaması hazırladık ve Add Reference diyalog kutusunu ekrana getirip System.Windows.Forms.dll referansının Solution Explorer penceresinde listelenmesini sağladık. Gerek duyulmayacak bazı referansları ise Solution Explorer penceresinden sildik.

Konsol uygulamaları için burada yazılanların pratik bir değerinin olmadığını ve amacın geri planda gelişen olaylar hakkında bilgi vermek olduğunu bilmenizi isteriz. Bu andan itibaren System.Windows.Forms adlı namespace’teki Class’lardan yararlanabiliriz. using bloğunda bu namespace’teki Class’ları kullanacağınızı işaret ederseniz Class adından önce namespace adını yazmak zorunda kalmazsınız.
Bu şartlarda konsol uygulamasında System.Windows.Forms’de yer alan sınıflardan yararlanmak mümkün olduğu gibi Application sınıfından yararlanabiliriz. Konu Application sınıfı olduğunda durup biraz üzerinde düşünmemiz gerekmektedir. Bir önceki bölümden bildiğiniz gibi Windows Forms Application şablonu ile hazırlanan her uygulama için Application sınıfının Run() metodu sayesinde bir mesaj kuyruğu hazırlanmakta ve uygulamanın Windows’la ilişkisi Application sınıfı üzerinden kurulmaktadır.
Her ne kadar Solution Explorer penceresinde System.Windows.Forms.dll referansının listelenmesini sağlayıp Application sınıfının bazı metotlarından yararlanmak mümkün olsa bile kontrol Application nesnesinde değildir. Bu konuyu netleştirmek için Project menüsünden komut verip ekrana Add New Item diyalog kutusunu getirip Windows Forms şablonundan yararlanıp konsol uygulamasına bir form dahil ettik.

Konsol uygulamasına Add New Items diyalog kutusundan yararlanıp “Form1” adında bir formu dahil ettikten sonra bu forma bir düğme yerleştirip bu düğmenin Click olayını temsil eden metotta Application sınıfının Exit() metodunu kullandık. Bir önceki bölümden hatırlayacağınız gibi Application sınıfının Exit() metodu o sırada çalışan Windows Forms uygulamasının çalışmasını sona erdirmektedir.
private void Cikis_Click(object sender, EventArgs e)
{
Application.Exit();
}
Şimdi sırada konsol uygulamasının Main() metodunu düzenleyip uygulama çalıştırıldığı zaman yukarıda uygulamaya dahil edilen formu ekrana getirmek var. Bu amaçla Main() metoduna yazılan satırları aşağıda görebilirsiniz.
namespace Konsol_uygulamasi
{
class Program
{
static void Main(string[] args)
{
Form1 F1 = new Form1();
F1.ShowDialog();
Console.ReadKey();
}
}
}
Tahmin ettiğiniz gibi Main() metodu bu şekilde düzenlenen konsol uygulaması çalıştırıldığında Form1 sınıfının örneği alınıp ShowDialog()ile ekrana getirilir. Kullanıcı formdaki “Çıkış” başlıklı düğmeyi tıklarsa form kapatılır ve programın işletimi Main() metodundaki bir sonraki satıra yani Console sınıfının ReadKey() metodunun kullanıldığı satıra geçer. Ne zamanki kullanıcı konsolda bir tuşa basarsa Main() metodundaki bütün satırlar işletilmiş olacağı için konsol uygulamasının çalışması sona erer. Başka bir deyişle Application sınıfının Exit() metodunun konsol uygulamasının çalışmasına bir etkisi olmadı. Exit() metodu ancak konsol uygulaması dahilinde hazırlanan formlar üzerinde etkili olabilmektedir.
Dikkat ederseniz yukarıda konsol uygulaması dahilinde form nesnesini ekrana getirirken ShowDilaog() metodunu kullandık. Sizce ShowDialog() yerine Show() metodunu kullansaydık ne olurdu? Hata meydana gelirdi ve konsol uygulaması çökerdi. Çünkü Show() metodu ile ekrana getirilen form, Application nesnesine gerek duyar. Bunun için ya tıpkı Windows Forms uygulamalarında olduğu gibi hazırlanan form nesnesi Application sınıfının Run() metoduna parametre olarak verilmeliydi ya da Show() metodu ile form ekrana getirildikten sonra Application sınıfının Run() metodu işletilmelidir.
static void Main(string[] args)
{
Form1 F1 = new Form1();
F1.Show();
Application.Run();
Console.ReadKey();
}
Bu andan itibaren ekrana getirilen form normal Windows Forms uygulamasından farksızdır. Bu şekilde ekrana getirilen form kapatılırsa veya Application sınıfının Exit() metodu işletilirse Application nesnesi uygulamanın çalışmasını sona erdirir.
Burada yaptıklarımızı özetlemek gerekirse şunlar söylenebilir: Konsol uygulaması dahilinde Windows Forms uygulaması hazırlayıp çalıştırdık. Tabi bu önerilecek bir yöntem değildir. Bu bir bakıma Windows Forms uygulaması hazırlayıp sonra da Project menüsünden komut verilerek ekrana getirilen Properties penceresinde uygulamanın Output type özelliğini Console Application olarak ayarlamak gibidir. Windows Forms uygulamasının çıkış tipini konsol uygulaması olarak ayarlarsanız formdan önce konsol penceresi açılır.
Her ne kadar yukarıdaki sayfalarda Main() metodunun parametreli çalıştırılmasından söz edilmiş olunsa bile konsol uygulamalarını Visual Studio ile geliştirenler açısından konuyu ele almamıştık. Visual Studio ile hazırlanıp Debug menüsündeki Start Debugging komutu ile test edilmek istenen uygulamanın Main() metoduna parametre gönderilmek isteniyorsa Project Properties penceresinde Debug sekmesindeki Command line arguments kutusuna parametreleri sıra ile yazmak gerekir.

Visual Studio’yu Taklit Etmek
Yukarıdaki sayfalarda yazılanlara dikkat ettiyseniz konsol uygulamasını Visual Studio ile hazırladığınızda ilgilendiğiniz namespace’leri içeren referans veya DLL dosyalarını Solution Express penceresinde kolayca listeleyebiliyorsunuz. Ancak Visual Studio’dan yararlanmadan hazırladığınız konsol uygulamasında System dışında herhangi bir namespace’in kaynaklarını kullandığınızda derleme yaparken bu namespace’in yer aldığı referans veya DLL dosyasından derleyiciyi haberdar etmek gerekiyor. Bu konuda bilgi vermek için aşağıdaki gibi basit bir konsol uygulaması hazırladık.

Sizin için herhangi yeni bir şey içermeyen bu kodu dikkatlice incelerseniz System adlı namespace’te dolayısıyla “System.dll” dosyasında yer alan Console sınıfından yararlanıldığını görürsünüz. DOS penceresinde derleme işlemini aşağıdaki gibi yapmamıza rağmen, başka bir deyişle derleyiciyi System.dll’den haberdar etmemiş olmamıza rağmen derleme başarılı bir şekilde gerçekleşti.

Çünkü derleyici System.dll dosyasını otomatik olarak refere etmektedir. Bu nedenle konsolda çalıştırılmak üzere hazırlanan bu C# programı aşağıdaki gibi derlense bile değişen bir şey olmaz.

Bu derleme satırında derlenecek CS dosyasını işaret ettikten sonra reference parametresi ile ilgili DLL dosyasını işaret ettik. Şimdi yukarıda verilen konsol uygulamasında değişiklik yapıp System.Windows.Forms’deki Form ve Application sınıflarından yararlanacağız.
using System.Windows.Forms;
namespace deneme
{
public class Form1 : System.Windows.Forms.Form
{
public Form1()
{
this.Text ="Form1";
}
}
public class anasinif
{
public static void Main()
{
Form1 nesne = new Form1();
Application.Run(nesne);
}
}
}
2 sınıfın olduğu bu konsol uygulamasındaki Form1 sınıfı System.Windows.Forms’deki Form sınıfının mirasçısı olup yapıcı metodunda Text özelliğinin içeriği değiştirilmektedir. Main() metodunun olduğu 2. Class’ta ise ilk sınıfın örneği alınıp Application sınıfının Run() metoduna parametre olarak verilmektedir.
Bu kodu derleyip çalıştırdığınızda ekrana “Form1” başlıklı bir pencerenin geleceğini tahmin edebilirsiniz. Bu uygulamada “System.Windows.Forms.dll” adlı reference’ten yararlanıldığı için derleme yapılırken bu DLL dosyasının aşağıdaki gibi reference parametresi ile işaret edilmesi gerekir. Bu derleme satırında reference parametresini 2. kez kullanıp başka bir referanstan derleyiciyi haberdar edebilirsiniz.

Not Defteri veya başka bir şekilde hazırladığınız uygulamayı DOS penceresinde kendiniz derlerken uygulamanızın konsol uygulaması olduğu varsayılır. Dolayısıyla aşağıdaki gibi kod yazıp derleme yaparsanız ekrana formdan önce DOS penceresi gelir.

Her ne kadar bu uygulamanın konsolla bir işi olmasa bile bu uygulama yukarıdaki sayfalarda anlatılan şekilde derlenirse Target parametresinin “exe” olduğuna karar verilir ve Windows formu ile birlikte DOS penceresi de açılır. DOS penceresinde derlediğiniz uygulama Windows Forms uygulaması ise derlemeyi aşağıdaki gibi yapabilirsiniz.

Bu şekilde Visual Studio yararlanmadan Not Defteri ile Windows Forms uygulamasının nasıl hazırlandığını gösterdikten sonra şimdi Visual Studio’yu kullanmadan Visual Studio ile hazırlanan uygulamanın benzerini hazırlayacağız. Bu amaçla “C:” sürüsünün kök klasöründen “\Projem” adında bir klasör hazırlayıp Not Defteri ile aşağıdaki gibi bir “Program.cs” dosyası hazırlayıp bu klasöre kaydettik. Bu dosyaya Program.cs yerine başka bir ad verebilirdik. Bu dosyanın önemi Main() metodunu içermesidir.

Visual Studio’nun hazırladığından biraz kısıtlı bir “Program.cs” dosyasını bu şekilde hazırlayıp yukarıda adını andığımız klasöre kaydettikten sonra yine Not Defteri aşağıdaki gibi bir “Form1.cs” dosyası hazırladık.

Visual Studio tarafından using deyimi ile koda dahil edilen bazı namespace’lerdeki class’lara bu projede gerek duyulmadığı için dahil etmedik. Aslında using deyimi ile işaret edilen namespace’lerin koda dahil edildiğini söylemek tam doğru değildir. Bu konunun ayrıntıları daha sonra anlatılacaktır. Şimdi sırada “Form1” adlı Partial Class’ın diğer kısmını yazmak var. Bu amaçla Not Defteri ile aşağıdaki gibi bir “Form1.Designer.cs” dosyası hazırladık.

Bu şartlarda hazırlanan projenin kodları 3 ayrı CS dosyasında bulunmakta ve System.Windows.Form adlı namepaces’ten yararlanılmaktadır. Bu namespace System.Windows.Forms.dll adlı referansta yer aldığı için derleme satırını aşağıdaki gibi düzenledik. Tahmin edeceğiniz gibi konsol uygulamasında birden fazla referanstan yararlanıldığı zaman derleme satırı oldukça uzun olacaktır. System.dll dosyası derleme sırasında uygulamaya otomatik olarak refere için derleme satırına yazmaya gerek yoktur.
C:\Projem>CSC /out:Projem.exe Program.cs Form1.cs Form1.Designer.cs /reference: System.Windows.Form.dll
Bu şekilde yapılan derleme sonucu “Projem.exe” adında bir EXE dosya hazırlanır. Her ne kadar bu program dosyası çalıştırıldığında ekrana “Form1” başlıklı bir pencere gelse bile bu uygulama konsol uygulaması sayılmaktadır. Uygulamanın Windows Form uygulaması olarak değerlendirilmesini sağlamak için /target:winexe parametresi ile derlemek gerekiyor.
Şimdi Not Defteri ile hazırladığımız bu proje dahilinde ekrana getirilen forma bir Button nesnesi yerleştireceğiz. Bu amaçla Form1 sınıfının InitializeComponent() metodunu aşağıdaki gibi düzenledik.

Bu şekilde 3 dosya şeklinde düzenlenen konsol uygulaması derlenip çalıştırıldığında aşağıdaki gibi bir sonuç alınır. Formdaki bu düğme tıklandığı zaman işletilmek üzere kod yazmak mümkün olmakla birlikte Visual Studio dururken Not Defteri ile proje geliştirmek pek mantıklı olmayacağı için konuyu fazla uzatmadık.

MSBuild Programı
Şimdiye kadar anlatılanlara göre Visual Studio ile Windows Forms Application şablonu ile hazırlanan projeler çok sayıda dosyadan meydana gelmektedir. Çok sayıda dosyadan meydana gelen projeleri konsolda derlemek zordur. Bunun çözümü .NET Framework ile gelen MSBuild programıdır. Bu programın bulunduğu yeri aşağıda görebilirsiniz.

Bu program esas olarak Visual Studio ile veya kendi hazırladığınız projeleri csproj uzantılı proje dosyasından yola çıkarak derlemektedir. Bu konuda bilgi vermek için Visual Studio’yu kullanarak “C:” sürücüsünde “\Proje1” aldı klasörde Proje1 adlı bir proje hazırlayıp kaydettik. Şimdi bu projeyi Visual Studio’yu kullanmadan MsBuild ile derleyeceğiz. Bu amaçla projeye ait klasöre geçip bu programı aşağıdaki gibi kullandık.

Bir Sonraki Bölüm : Namespace’ler
Her ne kadar C# İle Programlamaya Giriş ve Konsol Uygulamaları bölümlerinde namepace’lerden zaman zaman söz edilse bile namespace’leri ayrı bir bölüm olarak ele almanın zamanı geldi. Çünkü bu kitapta en çok sözü edilen kavramlardan birisi namespace’tir. Konu namespace olduğunda ise kayıtsız kalınamayacak kavramlardan birisi referans olmaktadır. Bir sonraki bölümde namespace kavramı bütün ayrıntıları ile olmasa bile bu kitabın ileriki sayfalarında yazılanların anlaşılabilmesi için yeteri ölçüde bilgi verildi. Tabii namespace ve referans kavramlarını iyice benimseyebilmek için bu kitabın Assembly adlı bölümünde yazılanları okumak gerek.
Fark etmiş olabileceğiniz gibi bu kitabın ilk 80 sayfasını geride bıraktık. Bu kitaptan azami verimi almak için bu 3 bölümde yazılanlar iyice kavranmadan diğer bölümlere geçilmesini önermiyoruz. Çünkü bu 3 bölümde hem birbirini tamamlayan hem de C#’ı öğrenip Visual Studio ile program geliştirmek isteyenlerin öncelikle öğrenmesi gerekli konular kuşbakışı bir anlayışla anlatıldı. Başka bir deyişle bu 3 bölüm sayesinde C# ve nesneye yönelik programcılık konularında anlatılacakları kavrayacak bir altyapıya sahip olmanız hedeflendi.
Konu programcılık konulu kitaplar olduğunda “asıl olan” anlatım biçimidir. Yoksa bu kitapta sözü edilen konuların çoğunu başka kaynaklarda bulabilmeniz mümkündür. Bazı yazarlar hedefledikleri okur grubu için C# hakkında bilgi verirken bazı konulara kendince ağırlık verir, bazı konulara şöyle bir değinirken bazı konulardan hiç söz etmezler. Örneğin şimdiye kadar inceleme şansı bulduğumuz hiçbir kitapta Application sınıfı bağımsız bir bölüm halinde anlatılmamıştı. Bazı yazarlar Application sınıfından Exit() metodunu kullandıkları için söz etmişlerken bazıları ise yarım sayfada anlatmışlardı. Bu kitapta Application sınıfı ile ilgili her şey anlatılmamış olunsa bile bu sınıf önemli olduğu için ayrı bir bölüm olarak düzenlendi. Yazarların tercihleri ne bir kitabı iyi yapar ne de değersiz. Asıl değerlendirme ölçüsü bizce şu olmalıdır: Yazarın sözü edilecek bir konuyu anlatırken yazdıkları kolay okunuyor mu hemen anlaşılıyor mu buna bakmak gerek.
* Meraklısı İçin Notlar
Bu kitabın ilk 80 sayfasını, normal dizilen kitaplara göre 100 sayfalık, şişirilen kitaplar ölçü alındığında ise 110 sayfayı geride bıraktık. Konsol uygulamaları hakkında bilgi verilen bu bölüm kitapta 32 sayfadır. Bu 32 sayfada sözü edilen bazı konulara her kaynakta rastlandığı gibi yerli yabancı hiçbir kitapta rastlamayacağınız konular da bulunmaktadır. Başka bir deyişle yerli yabancı her kitapta konsol uygulamalarıyla ilgili olarak sözü edilen bazı konular hakkında(örneğin Console sınıfı) bu kitapta da bilgi bulunmaktadır. Ancak yalnızca bu kitapta olan birkaç konu bulunmaktadır. Örneğin konsol uygulamaları penceresinden bakılıp Application sınıfı hakkında verilen bilgiye başka kaynaklarda rastlamanız düşük ihtimaldir. Hele hele “Visual Studio’yu Taklit Etmek” başlığı altında yazılanları hiçbir kaynakta bulamazsınız. İşin özü şudur: Bu bölümü okuyanların benzer konularda başka kaynaklara ihtiyaçları yoktur. Tabi “bozuk Türkçe ile kaleme alınmış çok sayıda teknik yanlışı içeren kaynaklara bakma ihtiyacım var” diyenlere sözümüz yoktur. Yazarlar kitapları neden mi şişiirrler? Çünkü kitapların fiyatları sayfa sayısına göre belirlenir. Kitap fazla sayıda sayfaya sahip oluırsa kitabın kapak fiyatı artar. Dolayısıyla yazarların eline daha fazla para geçer.