Visual C# kategorisi blog kayıtları
Collection Base

COLLECTION BASE SINIFI ILE KENDI KOLEKSIYONLARIMIZI YAZMAK

               

                Bu makalemizde CollectionBase sınıfından yararlanarak kendi koleksiyonumuzu yazıyor olacağız. Öncelikle koleksiyonların ne olduğunu hatırlayalım. Koleksiyonları ilk etapta bir dizi gibi düşünebiliriz.  Diziler aynı tipten veya farklı tiplerden birçok değeri taşımak için kullandığımız referans tipli yapılardır.Örnek olarak 5 gözlü bir integer dizisi için tanımlama aşağıdaki gibi oluyordu :

int[] sayilar = new int[5];

Bu şekilde tanımladığınız bir dizi ile 5 adet integer bilgiyi taşıyabiliriz. Böyle bir yapıda canımızı sıkan iki nokta var :

  1. Tüm değerlerin integer olması gerektiği, başka bir bilgi taşıyamıyor olmamız
  2. 5 sayıdan fazla taşımak istersek Array.Resize metotunu kullanmak zorunda kalmamız (ki kendisi C# a 2.0 ile birlikte eklenmiştir J)

Bu iki problemin birincisinden object dizisi kullanarak kolayca kurtulabiliyoruz. Fakat bununda yanında getirdiği bazı problemler var. Bu problemler den biri bu koleksiyonun içerisine object olduğu için herşeyi ekleyebiliyor olmamız.

İkinci problemden ise ArrayList veya benzeri bir koleksiyon kullanarak kurtulabiliyoruz.

ArrayList koleksiyonunda da biraz önce bahsettiğimiz problem yine geçerli. Koleksiyonları hem resize işlemlerinden kurtulmak için hemde object türünden değerler taşıdıklarından istediğimiz tiple çalışmak için tercih ederiz.Fakat  bir yazılım geliştirme ekibi içerisinde çalıştığınızı düşünürseniz ve siz sadece dll hazırlamak ile uğraşıyorsanız, tip güvenliğine önem vermeniz gerekecektir. Örneğin bir Ogrenci Takip programı yazarken öğrencilerin listesinin tutulduğu koleksiyonda bir DateTime değerin durması pek hoş olmayacaktır. Sebebi ise o koleksiyonu bir gridde veya dropdownlist içerisinde DataSource olarak kullanamayacak olmanız. Bu örnekler daha da çoğaltılabilir.

Framework 2.0 ile birlikte Generic tipler sayesinde çözülen bu problem 1.1 versiyonunda çalışırken CollectionBase vb sınıflar ile çözülüyordu. Bu makalemizde ki konumuz ise CollectionBase sınıfı ile bu işlemi nasıl çözüyor  olduğumuz.

CollectionBase sınıfı bir taban sınıf olduğundan dolayı kendisini instance çıkartarak kullanamıyorsunuz.  Aşağıda CollectionBase sınıfı ile ilgili bir metadata bilgisi yer almaktadır.

namespace System.Collections

{

    [Serializable]

    [ComVisible(true)]

    public abstract class CollectionBase : IList, ICollection, IEnumerable

    {

        protected CollectionBase();

        protected CollectionBase(int capacity);

        [ComVisible(false)]

        public int Capacity { get; set; }

        public int Count { get; }

        protected ArrayList InnerList { get; }

        protected IList List { get; }

 

        public void Clear();

        public IEnumerator GetEnumerator();

        protected virtual void OnClear();

        protected virtual void OnClearComplete();

        protected virtual void OnInsert(int index, object value);

        protected virtual void OnInsertComplete(int index, object value);

        protected virtual void OnRemove(int index, object value);

        protected virtual void OnRemoveComplete(int index, object value);

        protected virtual void OnSet(int index, object oldValue, object newValue);

        protected virtual void OnSetComplete(int index, object oldValue, object newValue);

        protected virtual void OnValidate(object value);

        public void RemoveAt(int index);

    }

}

      Metadata gibi bilgilerle cok fazla mesgul olmadan asıl kodlarımıza geçiyoruz. Öncelikle Ogrenci sınıfımızı hazırlayalım.

public class Ogrenci

    {

        static int sayac = 0;

        public Ogrenci()

        {

            this._siraNo = ++sayac;

        }

        int _siraNo;

        public int SiraNo

        {

            get { return _siraNo; }

        }

        string _isim;

        public string Isim

        {

            get { return _isim; }

            set { _isim = value; }

        }

        string soyIsim;

        public string SoyIsim

        {

            get { return soyIsim; }

            set { soyIsim = value; }

        }

        public override string ToString()

        {

            return "Adı - Soyadı : " + this._isim + " " + this.soyIsim;

        }

    }

      Class hakkında ufak bir açıklama yapmak gerekirse, öğrenci ile ilgili isim soyisim ve sira numarası gibi bilgilerimizi taşıyoruz. Fakat SıraNo değeri kullanıcı tarafından değil sistem tarafından veriliyor. Her instance oluşturulduğunda sınıftaki constructor sayesinde static ve private olan bir değişken bir arttırılıyor böylece sıra numarası sırayla birer birer arttırılıyor.    

      Şimdi gelelim koleksiyonumuzu oluşturmaya :

 

public class Sinif:CollectionBase

    {

        public void Ekle(Ogrenci ogr)

        {

            this.List.Add(ogr);

        }

 

        public void Ekle(Ogrenci ogr, int index)

        {

            this.List.Insert(index, ogr);

        }

 

        public void Sil(Ogrenci ogr)

        {

            if (this.List.Contains(ogr))

                this.List.Remove(ogr);

        }

        public void Sil(int index)

        {

            if (this.List.Count > index)

                this.List.RemoveAt(index);

        }

 

        public Ogrenci this[int index]

        {

            get { return (Ogrenci)this.List[index]; }

            set { this.List[index] = value; }

        }

    }

 

CollectionBase sınıfından türeme işlemi yaptığınız zaman sınıfınıza miras yoluyla List adında bir koleksiyon gelmektedir.IList türünden olan bu koleksiyon object türünden değer taşır ve önemli olan bu üye sınıfınıza protected olarak geçmektedir. Yani List ismindeki üyemizden kimsenin haberi yok J

Koleksiyon sınıfımıza iki adet ekle metotu iki adet sil metotu ve bir adet indexer dediğimiz tüm koleksiyonlardan alışık olduğunuz :

ArrayList liste = new ArrayList();

liste.Add(?123?);

liste[0]=?Abc?;

şeklinde kullandığımız indeksleyici bulunmakta. Bunları hazırladıktan sonra artık bu uygulamamızı kullanacak olan bir windows application hazırlamaya başlayalım. Aşağıdaki gibi bir form tasarımı hazırladım :

 

En üstten en alta doğru sırasıyla TextBox isimlerimiz :

·         txtAdi

·         txtSoyadi

·         txtSiraNo

·         txtAramaAdi

·         txtAramaSoyadi

Aşağıda ise Form1 içerisinde koleksiyonun kullanımının kodları bulunmakta, önce kodları inceleyelim sonra da kodlar üzerine konuşalım :

 

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

 

namespace CollectionBaseMakale

{

    public partial class Form1 : Form

    {

        public Form1()

        {

            InitializeComponent();

        }

 

        void Doldur()

        {

            listBox1.Items.Clear();

            foreach (Ogrenci ogr in liste)

            {

                listBox1.Items.Add(ogr);

            }

        }

 

        Sinif liste = new Sinif();

        private void btnEkle_Click(object sender, EventArgs e)

        {

            Ogrenci ogr = new Ogrenci();

            ogr.Isim = txtAdi.Text;

            ogr.SoyIsim = txtSoyadi.Text;

            liste.Ekle(ogr);

            this.Doldur();

        }

 

        private void btnBul_Click(object sender, EventArgs e)

        {

            if (!string.IsNullOrEmpty(txtSirano.Text))

            {

                int aranan = Convert.ToInt32(txtSirano.Text);

                foreach (Ogrenci ogr in liste)

                {

                    if (ogr.SiraNo == aranan)

                    {

                        txtAramaAdi.Text = ogr.Isim;

                        txtAramaSoyadi.Text = ogr.SoyIsim;

                        break;

                    }

                }

            }

            else

                MessageBox.Show("Arama işlemi için sıra numarası girmelisiniz!");

 

            this.Doldur();

        }

 

        private void btnDegistir_Click(object sender, EventArgs e)

        {

            if (!string.IsNullOrEmpty(txtSirano.Text))

            {

                int aranan = Convert.ToInt32(txtSirano.Text);

                foreach (Ogrenci ogr in liste)

                {

                    if (ogr.SiraNo == aranan)

                    {

                        ogr.Isim = txtAramaAdi.Text;

                        ogr.SoyIsim = txtAramaSoyadi.Text;

                        break;

                    }

                }

            }

            else

                MessageBox.Show("Arama işlemi için sıra numarası girmelisiniz!");

            this.Doldur();

        }

 

        private void btnSil_Click(object sender, EventArgs e)

        {

            if (!string.IsNullOrEmpty(txtSirano.Text))

            {

                int aranan = Convert.ToInt32(txtSirano.Text);

                foreach (Ogrenci ogr in liste)

                {

                    if (ogr.SiraNo == aranan)

                    {

                        liste.Sil(ogr);

                        MessageBox.Show("Silme işlemi tamamlandı!");

                        break;

                    }

                }

            }

            this.Doldur();

        }

    }

}

 

Yukarıdaki kodlarımızı açıklamaya başlayalım. Öncelikle Doldur ismindeki metot en alttaki listbox kontrolünü her işlemden sonra doldurmakla görevli. Onun haricinde görüldüğü üzere Global olarak bir Sinif nesnesi tanımlanmış. Daha sonra ekle düğmesine basıldığı zaman bu koleksiyona yeni bir öğrenci nesnesi ekleniyor. Tabiki otomatik olarak bir sıra numarası alıyor. Bul diyince sıra numarasına göre arama yapılıp aranan öğrenci bulunuyor. Değiştirme ve silme işlemide aynı bu yöntemle çalışıyor.

Bizim için asıl önemli olan konu koleksiyonumuzun özel bir tiple çalışıyor olması. Hazırladığımız koleksiyon object tipinden veriler kabul ederek değil de Ogrenci sınıfı ile çalışıyor böylece hazırladığınız koleksiyonda başka bir tip kullanma şansınız kalmıyor.

 

Bu makalede CollectionBase isimli sınıfa değinmiş olduk. Bir başka makalede görüşmek üzere hepinize iyi çalışmalar.

 

 

Sorularınız için

bora.burgucugil@bilgeadam.com

adresine mail atabilirsiniz.

 


C# Biliyorum - 3

            Visual Basic kodlamadan C# kodlamaya geçtiğimiz makalelerden üçüncüsü olan bu makalemizde, C# içerisindeki for, while ve do while yapılarına değiniyor olacağız. Visual Basic içerisinde sıkça kullandığımız, özellikle for, while ve do while yapıları C# içerisinde VB?e göre biraz farklı kodlanıyor. Öncelikle for dediğimiz yapıyı biraz hatırlayalım. En eski dostlarımızdan olan for her yazılım dilinde olduğu gibi C# içerisinde de bize yardım için hazır beklemekte.

 

For :

 

            Kısa bir tanım yapmak istersek for yapısı için söylenecek en güzel cümle sanırım, belirtilen bir başlangıç rakamından, bitiş rakamına kadar belirteceğimiz kodları tekrar tekrar çalıştıran kod parçacığıdır (döngü yapısıdır).

            Öncelikle for yapısının C# içerisinde ki şemasını inceleyelim.

 

 

Yukarıda ki kodları biraz açıklayalım. En başta integer türünden bir değişken tanıtılıyor. For içerisinde kırmızı ile işaretlenen alan bizim döngümüzün saymaya başlayacağı değerdir. Değişkenimize ilk değerini başka bir deyişle başlangıç değerini veriyoruz. Döngümüz 0(sıfır) dan başlasın. İkinci bölüm, mavi ile işaretlenen alan ise döngümüzün kaç kere döneceğini belirten bölümdür. Yani sayımız 0 (sıfır) dan başlasın, 10 oluncaya kadar dönsün.

 

Not: Küçüktür 10 dediğimiz için döngümüzdeki değişken olan sayim, 10 değeri için dönmeyecektir.

 

Üçüncü bölüm ise döngümüzün başlangıç ve bitiş değerleri arasında kaçar kaçar artacağı veya azalacağını belirler. Böylece yukarıda ki for döngüsü için şöyle bir tanım yapabiliriz. Sayim isimli değişkenimiz 0(sıfır) dan başlasın, 10 a kadar birer birer dönsün.Döngümüz 0 (sıfır) dahil olmak üzere :

 

0          1          2          3          4          5          6          7          8          9

 

rakamları için dönecek, 10 için dönmeyecektir. Şimdi gelelim for yapısının VB ile C# kodlamalarına. İlk önce VB içerisinde 0(sıfır) ile 10 arasındaki 2 ile tam bölünebilen sayıları bulan ufak bir program yazalım:

 

 

VB içerisinde geliştirdiğimiz bu program parçası kullanıcıya, 0 ile 10 dâhil olmak üzere, 0 ile 10 arasındaki 2 ile tam bölünebilen sayıları MessageBox ile bildirecektir. Şimdi gelelim bu program parçacığının C# taki karşılığına:

 

 

Gördüğümüz gibi VB içerisinde kullandığımız for ile C# içerisinde ki for yapısının tek farkı syntax. VB içerisinde:

 

            For değişken = başlangıç_değeri To bitiş_değeri

 

            Next

 

şeklinde bit tanımlama yapılırken. C# içerisinde:

 

            for (değişken = başlangıç_değeri; değişken <= bitiş_değeri; değişken artma veya azalma komutu)

 

            Şimdi gelelim şu step dediğimiz kavrama. Eğer biz döngümüzün birer birer artmasını değilde ikişer ikişer artmasını istiyorsak ne yapacağız. VB içerisinde:

 

 

C# içerisinde ise:

 

 

Şeklinde kodlanacaktır. Yani VB içerisinde step anahtar kelimesinden sonra verdiğimiz arttırma parametresi C# içerisinde for yapısının üçüncü bloğunda yer alıyor. Eğer 5?er 5?er arttırma yapmak istiyorsak += operatöründen sonraki 2 rakamı ile 5 rakamını değiştirmemiz yeterli olacaktır.

            Artan değil de azalan bir for kurmak istiyorsak, sayim++ şeklinde yazdığımız üçüncü blok yerine sayim- - yazmamız gerekmektedir. Yine birer birer değil de 2 şer 2 şer veya 5 er 5 er azaltma yapmak istiyorsak sayim -= 2 veya sayim -=5 yazmamız yeterli olacaktır.

 

            For yapısını anlayabilmek için en uygun kelime olduğu sürecedir. Yani başlangıç değerini verdiğimiz değişkenin değeri ikinci blokta tanımladığımız koşula uygun olduğu sürece döngümüz dönmeye devam edecektir.

 

While

 

            While hemen hemen for ile aynı mantığa sahip bir döngü yapısıdır. While ile for arasında ki tek fark for döngüsünde olduğu gibi iterasyonun (arttırma veya azaltmanın) tanımlama satırında olmamasıdır. Ne demek istediğimize kodlarla açıklık getirelim.

 

            İşe yine şemayı tanımlamakla başlayalım:

 

            While (koşul)

{

            //çalıştırılacak kodlar?

}

 

VB kodlaması:

 

 

C# kodlaması:

 

 

Görüldüğü üzere yukarıda for ile yaptığımız programı while ile yaparsak bu şekilde kod parçacıkları ortaya çıkacaktır. Biraz önce bahsettiğimiz iterasyonu kendimiz yapmalıyız cümlesinin anlamı ise kodlar da açık şekilde görünmekte. VB içerisinde sayim+=1 olarak veya C# içerisinde sayim++; olarak tanımladığımız kod parçası bizim iterasyonumuzu yani arttırma veya azaltma yöntemimizi belirtmektedir. Yukarıdaki kodlar da birer birer arttırma söz konusudur. Aynı for yapısında kullandığımız gibi iterasyonu birer birer yerine ikişer ikişer veya beşer beşer tanımlayabiliriz.

 

While yapısı içinde olduğu sürece mantığı geçerlidir. While anahtar kelimesinden sonra tanımladığımız koşul doğru olduğu sürece döngü dönmeye devam edecektir.

 

 

Do while:

 

            Do while yapısı while gibi çalışır fakat aralarında ufak bir fark vardır. İlk önce do while yapısının şemasını inceleyelim daha sonra farktan bahsedelim.

 

 

            do

{

 

            //çalışacak kodlar?

 

}while(koşul);

 

Do while yapısı aynı while ve for yapısı gibi belirtilen koşul doğru olduğu sürece dönmekle yükümlüdür. Fakat while yapısı ile arasında çok ufak bir fark vardır. O da while döngüleri her dönme işleminden önce (yani kodlarını çalıştırmadan önce) belirtilen koşulun doğruluğunu kontrol eder. Do while yapıları ise ilk önce kendi içerisine yazılan kodları çalıştırır daha sonra koşulu kontrol eder. Dolayısıyla while ile do while arasındaki farkı şu şekilde özetleyebiliriz. While koşul doğru değilse hiçbir şekilde çalışmayacaktır, fakat do while yapısında kodlar kesinlikle en az bir kez çalışacaktır.

 

 

 

 

            Şimdi gelelim bu döngüler içerisin de kullanılan bazı özel anahtar kelimelere.

 

Break:

            Break anahtar kelimesi döngüyü sonlandırmak için kullanılır. Döngü içerisinde herhangi bir satırda break anahtar kelimesi tanımlanmış ise döngü o satırda duracak ve sonlanacaktır.

 

 

            Yukarıdaki kod da gördüğümüz break deyimi sayim isimli değişkenin 5 değerine sahip olma anında çalışacaktır. Dolayısıyla sayim isimli değişkenin değeri 5 olduğun da döngü sonlandırılacaktır. Aşağıda while ve do while yapıları için kod örnekleri listelenmektedir.

 

 

Not: break anahtar kelimesi ile döngüden çıkıldıktan sonra döngü içerisinde ve break anahtar kelimesinin altında yer alan kodlar çalıştırılmaz.

 

While:

 

Do while:

 

            Bir başka anahtar kelime ise continue. Continue anahtar kelimesi break ile hemen hemen aynı mantığa sahiptir. Continue anahtar kelimesi de derleyici tarafından okunduğu anda döngü içerisinde ve continue anahtar kelimesi altındaki kodlar çalıştırılmaz. İşte tek fark bu noktada ortaya çıkmaktadır. Break altında ki kodları çalıştırmadan döngüden çıkarken, continue altındaki kodları bir seferlik çalıştırmadan döngüde tekrar iterasyon yapılmasını sağlayacaktır. Yani continue anahtar kelimesi çalıştığı anda altında bulunan kodları pas geçip döngüyü devam ettirecektir. Örnek olarak sadece ekrana 1 den 10 a kadar sayim isimli değişkenin değerini yazan ufak bir program geliştirelim.

 

 

            Yukarıdaki kod parçacığı çalıştırıldığı takdirde kullanıcıya 1 den başlamak üzere 10 a kadar MessageBox ile mesaj verilecektir. Yani kullanıcıya toplam 10 adet mesaj kutusu gösterilecek. Fakat yukarıdaki kodda yorum satırı olarak işaretlediğimiz bölgeyi aktif hale getirirsek, kullanıcıya 9 adet mesaj kutusu gösterilecektir. Örn:

 

 

            Yukarıdaki örnekte kullanıcının karşısına ?Döngü değeri: 5? gibi bir mesaj kutusu çıkmayacaktır. Sebep ise sayim isimli değişkenin değerinin 5 olması durumunda continue parametresinin verilmiş olmasıdır. Derleyici programı çalıştırırken if satırı doğrulandığı takdirde continue komutunu alacak ve for satırına geri dönecektir. Dolayısıyla sayim isimli değişkenin 5 değeri için MessageBox.Show(); satırı çalıştırılmayacaktır.

 

 

            Böylelikle C# Biliyorum ? 3 makalemizin sonuna geldik. Seri olarak devam edecek makalelerimizden dördüncüsünde metotlara giriş yapıyor olacağız.

            Başka bir makalemizde tekrar görüşmek üzere hepinize iyi çalışmalar.

 

 

 

Bilge Adam Bilgi Teknolojileri Akademisi

Bireysel Yazılım Geliştirme Eğitmeni - Beşiktaş

 


C# ile internet uzerinden dosya indirmek [ File Download in Windows Applications]

C# ile Windows, Mobile uygulamalarinda internet uzerinden dosya indirmek (File Download)


Windows form projeniz de formun üzerinde

URL bilgisi için bir textBox : txtUrl,

indirilen dosyanın nereye yazılacağı hakkında ise bir diğer textbox : txtHedef

olduğunu varsayalım. Aşağıdaki kod parçası internet üzerinden dosya transfer etmenizi sağlayacaktır.

 

Not : Eğer bir proxy server kullanıyorsanız o zaman WebProxy sınıfı aracılığı ile internete çıkış sağlamalısınız.WebProxy kodlarını aşağıdaki linkte bulabilirsiniz :

http://www.boraburgucugil.com/blog.aspx?bId=15

WebRequest req = WebRequest.Create(txtUrl.Text);

HttpWebResponse cevap = (HttpWebResponse)req.GetResponse();

Stream akim = cevap.GetResponseStream();

FileStream yaz = new FileStream(txtHedef.Text + "\\" + Path.GetFileName(txtUrl.Text), FileMode.Create);

BinaryReader okuyucu = new BinaryReader(akim);

BinaryWriter yazici = new BinaryWriter(yaz);

try

{

while (true)

{

yazici.Write(okuyucu.ReadByte());

}

}

catch

{

}

finally

{

yaz.Close();

okuyucu.Close();

yazici.Close();

}

MessageBox.Show("Download Complete");


C# ile Windows, Mobile uygulamalarda proxy üzerinden internete çıkış sağlamak

Eğer projenizin çalıştığı ağ internete bir proxy server aracılığı ile çıkıyorsa sizin programınızın da internet explorer daki ayarları uygulaması gerekir. Örnek

WebProxy wp = new WebProxy(txtSunucu.Text, Convert.ToInt32(txtPort.Text));

wp.Credentials = new System.Net.NetworkCredential(txtKullaniciAdi.Text, txtSifre.Text, txtDomain.Text);

HttpWebRequest.DefaultWebProxy = wp;

kullanıcıdan proxy server bilgisini ve port numarasını almalısınız. Bir de Proxy server üzerinde yetki sahibi bir kullanıcı adı, şifre ve domain ismini programa tanıtmalısınız.

Not : Eğer kullanıcı adında domain bilgisi geçiyor ise

Örn : kullaniciadi@myDomain.com gibi

credential bildirimini aşağıdaki gibi yapmalısınız :

wp.Credentials = new System.Net.NetworkCredential(txtKullaniciAdi.Text, txtSifre.Text);

 


C# Biliyorum - 2

         Bu makalemizde C# Biliyorum makaleleri serimizin ikincisinde C# içerisindeki döngülere ve kontrol mekanizmalarına değiniyor olacağız. Öncelikle bir önceki makalemizde ki bilgilerimizin üstüne yeni bir kat çıkacağımızı bu yüzden bir önceki makaledeki bilgileri unutmamamız gerektiğini unutmamanın da pratik ile sağlandığını belirtelim ve makalemize başlayalım.

            Kimimizin VB içerisinde kimimizin ise başka programlama dilleri içerisinde karşılaştırmak için kullandığımız kontrol mekanizmalarından en önemlisi IF yapısıdır. If yapısını en temel ifade ile anlatmaya çalışırsak, bir değeri başka bir değer ile karşılaştırıp aynı ise veya farklı ise  bazı işlemler gerçeklemek için kullandığımız kontrol yapısı diyebiliriz. Yani :

 

 

Yukarıda görülen resimdeki gibi bir program yazdığımızı düşünelim. Kullanıcıdan 1 ile 10 arasında bir rakam talep ediyoruz. Kullanıcının doğru girip girmemesi kendi insafına kalmış.

 

Not: Şimdilik kullanıcının örf ve adetlere uygun bir şekilde sadece rakam gireceğini varsayıyoruz. Karakter girerse ne olacağı makalemizin konusunun dışında kalıyor. Bu konuyu başka bir makalede irdeliyor olacağız.

 

txtTahmin isimli textBox kontrolüne kullanıcı bir rakam girecek. Daha sonra biz kod tarafında oluşturacağımız rastgele (Random) bir sayıyı alttaki txtSonuc isimli TextBox a yazacağız. Eğer iki sayı birbiri ile aynı ise ekrana MessageBox.Show() metodu yardımı ile bir uyarı mesajı vereceğiz.

            Bu karşılaştırmayı VB içerisinde yapmak için aşağıdaki gibi bir kod yazmamız yeterli oluyordu :

 

 

 

 

 

 

 

 

 

 

 

Yukarıdaki kodda eğer txtTahmin.text = txtSonuc.text ise yani tahmin textboxunun değeri sonuc textboxunun değerine eşit ise 5 numaralı satırdaki kod, eğer eşit degil ise 7 numaralı satırdaki kod çalışıyordu. Öncelikle bu kodun C# içerisindeki karşılığını görelim sonra biraz If kontrol mekanizmasını açıklayalım :

 

 

If kontrol mekanizması verilen iki değeri belirttiğimiz koşula göre karşılaştırıp geriye boolean (true / false) türden bir bilgi döndürür. If yapısını şema ile anlatmak istersek eğer

 

 

Bu şekilde bir şema açıklayıcı olacaktır. If satırında ?= =? olarak belirttiğimiz ifade koşulumuzdur. Yani solundaki değer ile sağındaki değerin birbirine eşit olup olmadığına bakıyor ve boolean türden bir değer döndürüyor. Bunun dışında hepimizin bildiği diğer karşılaştırma ifadeleri C#'ta da aynıdır

 

VB

C#

=

= =

>=

>=

<> 

!=

 

Visual Basic ile kodlama yaparken, if içerisinde tek satır değilde birden fazla satırın işlem görmesini istiyorsak özel bir şey yapmamıza gerek yoktu fakat C# içerisinde bunun için

süslü parantezleri kullanıyoruz.

{

 

}

 

Yukarıdaki örnekten ilerlemek istersek kullanıcı sayıyı doğru tahmin edemediğinde txtTahmin isimli textbox 'ın içeriğini temizleyelim :

 

 

Yukarıdaki şekilde de gördüğümüz gibi else bloğunda iki satır kod çalıştırmak istediğim için, iki satır kodu süslü parantezler arasına alarak çalışmalarını sağladık.

 

SWITCH :

 

Şimdi gelelim bir başka kontrol mekanizmasına. If gibi çalışan Visual Basic de Select Case yapısı olarak bildiğimiz yapının C# taki karşılığı Switch Case dir. Bu yapı bize ne gibi bir avantaj sağlıyor bunu görüyor olacağız.

 

 

 

Bu şekilde bir proje geliştireceğimizi düşünelim. Kullanıcı cmbAylar isimli comboBox kontrolünden bir eleman seçecek. Bizde o ayın hangi Mevsimde olduğunu bulup txtMevsim isimli textBox kontrolüne yazıyor olacağız.Öncelikle yapıyı inceleyelim :

 

Şema :

 

Yukarıdaki şemada görüldüğü gibi switch için şöyle bir tanım kullanmamız doğru olacaktır. Switch, birden fazla if else bloklarının okunabilirlik açısından daha kolay kodlanmasıdır. Mesela kullanıcıdan aldığımız bir sayının 1 ile 5 arasında hangi rakama karşılık geldiğini bulmak için if deyimini seçtiyseniz :

 

(VB) :

 

 

 

(C#) :

 

 

Bahsettiğimiz programı VB veya C# ile if yapısını kullanarak yazmak istiyorsak  bu şekilde kodlama yapabiliriz. Fakat bu kodlama öncelikle okunabilirlik açısından çok iyi değil. Switch deyimi ile bu okunabilirliği arttırabiliriz.Bunun dışında yukarıdaki if bloklarını else if deyimi ile değil, hepsini sadece if deyimi ile kodlasaydık, program akışı sırasında tüm if deyimleri okunacaktı ve yorumlanacaktı. Bu durumda da if bloklarında sadece MessageBox.Show("x rakamı girildi") gibi bir kod bloğu yerine uzun süren hesaplamalar veya veritabanı ile ilgili işlemler yapılıyor olsaydı, her bir satır için tüm if deyimleri tekrar tekrar kontrol edilecekti.

İşte ikinci olarak da bu sorundan kurtulmak için switch yapısını kullanıyor olacağız. Şimdi gelelim yukarıdaki ufak programın switch ile yapılmasına :

 

(VB) :

 

 

(C#) :

 

 

Çalışma mantığına değinecek olursak,

  • switch {} parantezleri arasında ki case blokları switch (koşul) satırındaki koşulun sonucu için seçenekleri sunar.
  • default : deyimi switch deyiminde tanımlanan case seçenek bloklarından hiçbirinin doğrulanamaması durumunda çalıştırılacak olan seçenek bloğunu ifade eder. Yukarıdaki örnekten gidecek olursak, kullanıcı eğer 7 rakamını girerse TextBox kontrolüne bu durumda switch yapısındaki hiçbir case bloğu çalışmayacaktır. Fakat case bloklarından sonra birde default deyimi ile tanım yaparsak case bloklarımızın hiçbiri çalışmaz ise default deyimi çalışacaktır.

 

  • Her case bloğunun bitişi break anahtar kelimesi ile tanımlanır.break anahtar kelimesi case bloğunun bittiğini ve başka case bloklarının kontrol edilmemesi gerektiğini, yani switch yapısından artık çıkılabilineceğini söyler.

 

Switch yapısı ile ilgili b,r konudan daha bahsedelim. Bazen girilen bir sayılın herhangi bir aralıkta olup olmadığını kontrol etmemiz gerekebilir. Mesela bizim mevsim örneğimiz bu konu için uygun olacaktır. Önce örneğimizi yapalım sonrada yorumlayalım.

 

 

Yukarıdaki kodda gördüğümüz gibi eğer seçilen ay Aralık, Ocak, Şubat aylarından herhangi biri ise Kış Mevsimi bilgisini txtMevsim isimli kontrolün text özelliğine yazacağız. Bunun için 3 tane case bloğuna ihtiyacımız var.Ama 3 case bloğunun içeriğini teker teker yazmaktansa yukarıdaki şekilde olduğu gibi birden fazla case bloğunun aynı kodları çalıştırmasını sağlayabiliriz.Yukarıdaki örnekte comboBox içerisinden seçilen elemanın index ini kontrol ediyoruz. Koşul olarak onu bildirdik ve çıkabilecek muhtemel bütün sonuçları case bloklarında tanımladık. cmbAy isimli combobox içerisinde 12 ayın  her birine karşılık gelen 12 adet eleman bulunmakta.

 

0: Ocak

1: Şubat

2: Mart

3: Nisan

4: Mayıs

5: Haziran

6: Temmuz

7: Ağustos

8: Eylül

9: Ekim

10: Kasım

11: Aralık

 

Bu elemanlardan

0,1,11 indexli olanlardan herhangi biri seçilirse txtMevsim isimli textbox ta Kış,

2,3,4   indexli olanlardan herhangi biri seçilirse txtMevsim isimli textbox ta İlkbahar,

5,6,7   indexli olanlardan herhangi biri seçilirse txtMevsim isimli textbox ta Yaz,

8,9,10 indexli olanlardan herhangi biri seçilirse txtMevsim isimli textbox ta Sonbahar,

 

bilgisi görünecek. Bu durumda kodlama yaparken

 

case 0:

case 1:

case 11:

            txtMevsim.Text := "Kış Mevsimi";

break;

 

kodları ile 3 seçenekten hangisi seçilirse seçilsin bu kodun çalışmasını istediğimizi bildirmiş olduk.

 

Switch kontrolünün kullanım kurallarından bahsedecek olursak.

  • Aynı seçenek için birden fazla case tanımlanamaz.
  • default bloğunun tanımlanması isteğe bağlıdır zorunlu değildir.
  • Seçenekler değişken olamaz.
  • Seçenekler tamsayı veya string ya da char dediğimiz veri tiplerinden olabilir.

 

 

Böylelikle bir makalemizin daha sonuna geldik. Bir sonraki makalemiz de C# içerisindeki döngü yapılarına değiniyor olacağız.

 

Başka bir makalemizde tekrar görüşmek üzere hepinize iyi çalışmalar.

 

Bora BURGUCUGİL

bora.burgucugil@bilgeadam.com

---------------------------------------------

Bilge Adam Bilgi Teknolojileri Akademisi

Bireysel Yazılım Geliştirme Eğitmeni - Beşiktaş

 


Visual Basic'den C#'a geçiş

         Bu makalemizde Visual Basic kodlamadan, C# kodlamaya geçişi inceliyor olacağız. Öncelikle bazı gerekli olan sembollerle başlayalım makalemize. C# için kısa bir tanım yapacak olursa C# için C++, java ve Visual Basic dillerini bir araya getirerek ortaya bir harman çıkarıldığı söylenir. Zaten bu yüzdendir ki Microsoft C# diline fazlasıyla güvenmektedir. Peki C# dilinin ne gibi kalıpları ve kesin kuralları var acaba. Öncelikle C# kodlaması yaparken dikkat etmemiz gereken noktalar var bunlardan en önemlisi hemen hemen her kod satırımızın noktalı virgül ile sonlanmasıdır.

Neden hemen hemen dediğimi makalenin ilerleyen bölümlerinde görüyor olacağız. Şimdilik ön fikir olması amacıyla şunu söyleyelim. C# ta her satırın sonuna noktalı virgül (;) yazmak zorundayız. Ama if , for , while , try..catch blokları vs. karşılaştırma ifadelerinin veya döngülerin yada kontrol bloklarının sonuna ve de tanımlamaların örnek olarak class veya metot tanımlaması gibi yerlerde satırların sonuna noktalı virgül yazmıyoruz.C# ın dikkat edilmesi gereken ve asla unutulmaması gereken özelliklerinden biride Case Sensitive bir dil olmasıdır. Bu ne demek ?

C# ta tanıttığınız bir değişken veya kullanacağınız herhangi bir komutu tam ve doğru yazmalısınız, küçük harflerine ve büyük harflerine dikkat ederek yazmalısınız. Bu yüzden de bir C# programcısının ctrl+space kombinasyonu nu uyurken bile tekrarlaması her zaman doğaldır.

 

Konumuza değişken tanımlamaları ile başlayalım.

 

VB içerisinde :

 

 

şeklinde tanıttığımız değişkenleri CSharp içerisinde :

 

 

şeklinde tanıtıyoruz. Bunun anlamı nedir? Visual Basic içerisinde değişken tanımlamayı :

 

Dim değişken_adi As veri_tipi

 

formatında yaparken, C# içerisinde :

 

Veri_tipi değişken_adi;

 

formatında yapıyoruz.

 

Bunun dışında değişkenlere değer atamada hiçbir fark yoktur. Değişken adı = değer gibi bir atama satırı c# içerisinde de kabul görecektir.

 

Bu noktada biraz Visual Basic içerisinde sağlanmış kolaylıkların C# içerisinde olmamasından bahsedelim. Bunlardan en çok göze batanı tip dönüşümüdür. Visual Basic içerisinde :

 

 

Şeklinde bir atama yaptığınızda yani string tipten bir değişkeni alıp integer tipten sayi isimli değişkene yazdığınızda VB sizin için dönüştürme işlemini gerçekleştirecektir.

Programı çalıştırdığınızda ekrana ilk önce 0(sıfır) yazan bir mesaj kutusu daha sonra da yazi değişkeninin içeriği olan ?? sıfır karaktere sahip string türden veri içeren bir mesaj kutusu göreceksiniz. Yani programda sorun çıkmayacaktır ve çalışacaktır, fakat C# dilinde durum biraz farklı olacaktır

 

 

Resimde de gördüğümüz gibi C# içerisinde VB de gerçekleşen otomatik dönüştürme gerçekleşmiyor. Bu dönüştürme işlemini C#, programcının yapmasını ister. Bunun dışında resimde görüldüğü gibi ilk mesaj kutusu satırının da altı çizilmiştir. Bunun sebebi ise yine aynı şekilde tür dönüşümünü C#?ın sizden beklemesidir.

 

sayi = yazi; satırın da yazi değişkenini integer tipine

 

MessageBox.Show(sayi); satırında ise sayi değişkenini string veri tipine çevirmenizi bekler derleyici.

 

Kodu doğru yazmak istersek. Yapmamız gereken şunlardır:

 

 

Demek ki C# içerisinde tür dönüştürmeyi asla unutmuyoruz. Şimdi biraz yukarıdaki kodları açıklayalım. Değişkenlerimizi tanıttıktan sonra formumuzun load olayında bir değer ataması yapıyoruz ve integer bir değişkene string türden veriyi aktarıyoruz. Bunu yapabilmek için .Net Framework içerisindeki hazır ve de nazır bulunan, bizim kullanmamızı bekleyen sınıflardan biri olan Convert sınıfının ToInt32() metodunu kullanıyoruz. Metot bizden string değeri alıyor ve geriye integer türden değer döndürüyor. Bunun dışında yukarıdaki kodlarda gördüğümüz ToString() isminde bir kod daha var bu ne işe yarar dersek bu kod ise her tipten değişkenin üzerinde bulunan bir metottur. Tanıttığınız her değişkenin sonuna bir nokta koyduğunuzda ToString() metodunu görebilirsiniz, kullanabilirsiniz. Bu metodun yaptığı iş ise değerin veri tipi ne olursa olsun belirttiğiniz değişkenin değerini string olarak geriye döndürmesidir. Yukarıda ki kodda MessageBox.Show() metodu string bir değer istemektedir, ekrana yazacağı mesaj için. Bizim verdiğimiz değişkenin veri tipi ise integer olduğu için yine bir dönüştürme gereklidir. Ama bu sefer Convert sınıfından faydalanmamamızın sebebi ToString() metodunun tip ne olursa olsun her değişkenin üzerinde bulunuyor olmasıdır.

 

 

Not : Yukarıdaki resimde string yazi tanımlamasında yazi değişkeninin altının yeşil renk ile çizilmiş olmasının sebebi sadece bir uyarı almamızdır. Programın çalışması engellenmez ama uyarı programcıya gösterilir. Uyarının içeriği yazi isimli string türden tanıtılmış değişkenin bir ilk değer almamış olmasıdır. İlk değeri kodlayan tarafından verilmemiş bir string değişkenin ilk değeri derleyici tarafından null olarak atanır.

 

Şimdi biraz ilerleyelim ve gelelim dizilere. Tabiî ki dizilerin işleyişi anlamında hiçbir programlama dilinde fark oluşmayacaktır. Ama tanımlanırken bazı farklılıklar oluşabiliyor özellikle bizim makalemizin konusu olan C# ile VB arasında :

 

VB içerisinde

 

 

Şeklinde tanımlanan integer tipten bir dizi 6(altı) adet göze(elemana) sahip olacaktır. Yani Visual Basic içerisinde tanımlanan bu diziyi bir çekmeceye benzetecek olursak :

 

 

Yukarıdaki resimde görüldüğü gibi Visual Basic içerisinde bir dizi tanımlandığında kaç elemana sahip olacağı belirtildiği zaman Örnek 5 yazıldığında 5 indexli eleman açılana kadar göz eklenmeye devam edilecektir. Yukarıdaki dizi tanımı o zaman şöyle düşünülebilinir. 6 gözlü bir dizi, en son indisi 5. Programlama da her zaman diziler 0(sıfır)  indis ile başlar (indis = index). Dizinin kaç gözlü olduğunu saymaya çalıştığımızda ise 1 ile başlayacağımız için 6 gözlü bir dizi şeklinde bir ifade kullanıyoruz. Fakat C# içerisinde işler biraz değişik :

 

 

C# içerisinde yukarıda görüldüğü gibi tanımlanan bir dizi 5 elemana sahip olacaktır. Ve doğal olarak en son indisi 4 olacaktır. Bu da demek oluyor ki C# içerisinde diziye kaç gözlü olacağını söylersiniz, Visual Basic te dizinin en son kaçıncı indisi alacağını belirtirsiniz. Visual Basic örneğinde proje çalıştırıldığında ekrana 6 yazarken C# projesi çalıştırıldığında ekranda 5 değeri görülecektir.

 

Diziler konusunu öğrendiğimize göre Visual Basic içerisinde kullandığımız sub ve function ların C# içerisindeki karşılıklarını da görelim.

 

VB içerisinde kodlama yaparken bazı kodları tekrar tekrar yazmamız gerekebilir. Genellikle hesaplama işlemlerinde bu sorunla çok karşılaşırız. Bir satış programında kullanıcıdan kaç adet ürün alacağı bilgisini istersiniz ve birim fiyat sizin veritabanınızda sorgulanmayı beklemektedir. Sizde satış ekranında iken bu bilgiyi veritabanından okursunuz daha sonra adet ile birim fiyat değerini çarparsınız. Üzerinden KDV ayırırsınız. Hatta ürünün veritabanında tanımında belki genel bir iskonto  oranı vardır, onu da hesaplayıp toplam tutardan düşmeniz gerekmektedir. Sadece satış ekranını düşündüğümüzde her şey çok güzel ve sorunsuzdur. Sadece satışı yaparken okuyacaksınız çarpacaksınız böleceksiniz ve çıkartacaksınız. İşlem bu kadar. Fakat senaryoyu şöyle değiştirdiğimizde aynı projede birde stok modülü olsun ve bu sefer siz müşterisiniz ve bir de toptancınız var. Toptancıdan kaç adet ürün alacağınızı belirteceksiniz toptancı size birim fiyatı ile istediğiniz adeti çarparak, üzerine KDV sini hesaplayıp ekleyecek ve yine tanımlı ise size iskonto yapıp bunu toplam tutardan düşecek. Hala bir sorun yok ama siz aldığınız ürünlerin stok ve fiyat bilgilerini tutarak projenizde bir maliyet analizine ulaşmak istiyorsanız bu alış bilgilerinin de hepsini veritabanınızda tutmanız gerekecektir. Dolayısıyla biraz önce satış için yaptığınız hesaplamaların aynısını bu sefer kendi aldığınız ürün için yapıp veritabanınıza yazmanız lazım ki ileride bir üründen ne kadar kar ettiğinizi öğrenebilesiniz. Bu örnekten çıkartacağımız sonuç şu olmalıdır. Hem satış hem de stok için aynı kodu iki kere yazacağımıza bu hesaplama kodunu bir kere yazarız, ve hesaplama yapacak olan yerlerden bu kodları çağırıp çalıştırırız. İşte bu aşamada karşımıza VB içerisinde Sub veya functionlar çıkıyordu. Sub da function da içerisine yazdığımız bir grup kodu çalıştırmaya yarıyordu, aralarındaki tek fark subların sadece verilen kodları çalıştırması, functionların ise çalıştırdıktan sonra geriye bir değer döndürebiliyor olmalarıydı. O zaman hemen VB içerisinde bir sub örneği görelim :

 

(Not : Sub ların programlama da ki karşılığı prosedür(procedure), functionlar ise aynı şekilde fonksiyon ismini alırlar.)

 

 

Resimde görüldüğü üzere FiyatHesapla isimli sub, class üzerinde tanımlanmış netTutar isimli değişkene aldığı parametreler üzerinden bir hesap yapıp değer aktarıyor. Bunun birde function olarak karşılığını görelim dersek :

 

 

VB içerisinde Function tanımını da bu şekilde yapıyorduk. Şimdi gelelim bu programın C# ile kodlanmış haline. C# içerisinde prosedürler ve fonksiyonlar metot ismi altında toplanmıştır sub veya function gibi keyword ler ile ayrılmazlar tanımlanmaları şu şekilde olmaktadır. Önce sub karşılığı ile başlayalım :

 

 

Yukarıdaki resimde görüldüğü üzere C# içerisinde Sub veya function keyword leri kullanılarak bir tanım yapılmamaktadır. Birde C# içerisinde function karşılığını görelim sonra yorumlamaya başlayalım.

 

 

Yukarıdaki iki resimden de anlaşılacağı üzere C# içerisinde Sub dediğimiz geriye değer döndürmeyen prosedürlerin yerini void olarak tanıttığımız metotlar almaktadır. Function ların yerini ise geriye herhangi bir tipten (Örn : string, int, double, decimal, herhangi bir sınıf veya herhangi bir dizi vs) değer döndüren fonksiyonlar almaktadırlar. Prosedür dediğimiz, VB içerisinde Sub olarak geçen ve C# ta da void olarak geçen metotlar geriye (VB) nothing (C#)null, yani hiçbir şey döndürürler. Bu yüzden C# içerisinde onlara void değer döndüren metotlar diyoruz. Fakat fonksiyonlar ise geriye bir değer döndürmek zorundadır. Bunu da VB içerisinde function tanımının sonunda belirtiyorduk veya belirtmezsek kendisi tahmin ediyordu J C# içerisinde ise metodu tanımlarken belirtiyorduk. Bunları anlattıktan sonra C# içerisinde metot  tanımlaması şablonunu görelim :

 

Metotun_dondureceği_veri_tipi   metotun_ismi   (aldığı_parametreler)

 

*En baştaki metodun döndüreceği veri tipi void veya bir veri tipi olmalıdır. Boş geçilemez.

*Bir Sub yazmak istiyorsak metodun geri  döndüreceği veri tipi yerine void yazıyoruz

*Bir Function yazmak istiyorsak metodun geri döndüreceği veri tipi yerine int string vs gibi veri tipini yazıyoruz.

*Metoda bir isim vermek zorundayız.

*En sona parantez açılıp kapatılmak zorundadır. Parantezler arasına senaryo gerektiriyorsa parametrelerimizi ekleriz.

*Metot parametre almadan çalışacak ise parantezler arasını boş bırakırız.

*Bu şekilde tanım yapıldıktan sonra { } süslü parantez bloğu yazılmak zorundadır.

Süslü parantezler arasına çalışmasını istediğimiz kodları yazarız. VB içerisinde kullandığımız EndSub, EndFunction gibi kod satırları C# içerisinde yazılmamaktadır.

 

Böylelikle C# Biliyorum -1 makalemizin sonuna geldik. Seri olarak devam edecek makalelerimizden ikincisinde kontrol mekanizmalarına ve döngülere değiniyor olacağız.

Başka bir makalemizde tekrar görüşmek üzere hepinize iyi çalışmalar.

 

Bora BURGUCUGİL

----------------------------------------------------------

Bilge Adam Bilgi Teknolojileri Akademisi

Bireysel Yazılım Geliştirme Eğitmeni - Beşiktaş


C# 3.0 Specification

C# 3.0 ile ilgili specification dökümanına buradan erişebilirsiniz.


Property Accessor Modifiers

            Property, Object Oriented Programming içerisinde hepimizin sıklıkla kullandığı bir yapıdır. Amacı temelde, değişkenlerin tanımlandığı sınıf dışarısından kontrolsüz değişikliğe uğramasını engellemek veya değer okuma işlemi yapılacağı zaman araya girip ister kontrol, ister değişik formatlarda değeri sunmaktır. Örneğin değişkenin alabileceği sınırlandırmak isterseniz bunu property aracılığı ile rahatça gerçekleştirebilirsiniz. Property kavramını hatırlayalım :

                       

    class Ogrenci

    {

        int _yazilim;

        int _sistem;

 

        public int Yazilim

        {

            get { return _yazilim; }

            set { _yazilim = value; }

        }

        public int Sistem

        {

            get { return _sistem; }

            set { _sistem = value; }

        }

    }

 

Yukarıdaki gibi bir sınıfımız olduğunu düşünürsek sınıf dışından sadece property ler erişilebilecektir. Bu sınıfın taşıyabileceği değerleri sınırlandırmak istersek :

 

using System;

using System.Collections.Generic;

using System.Text;

 

namespace PropertyAccessors

{

    class Program

    {

        static void Main(string[] args)

        {

            Ogrenci ogr = new Ogrenci();

            ogr.Yazilim = 150;

 

            Console.WriteLine("Not : " + ogr.Yazilim);

        }

    }

 

    public class Ogrenci

    {

        int _yazilim;

        int _sistem;

 

        public int Yazilim

        {

            get { return _yazilim; }

            set

            {

                if (value <= 100)

                    _yazilim = value;

            }

        }

        public int Sistem

        {

            get { return _sistem; }

            set

            {

                if (value <= 100)

                    _sistem = value;

            }

        }

    }

}

 

Çıktı :

 

 

Görüldüğü gibi kullanıcıyı rahatlıkla sınırlandırabiliyoruz. C# 2.0 ile birlikte gelen yeni bir yapı ise Property Accessor Accessibility kavramıdır. Bu yapı sayesinde artık bizim property accessor olarak nitelendirdiğimiz get ve set metotlarımızı da erişim belirteçleri ile sınırlandırabiliyoruz.

 

            Buraya kadar her şey güzel hiçbir sorun yok. Fakat bu property lere olan erişim tanımlandığı namespace haricinde başka bir namespace içerisinden mümkündür. Sebebi ise public olmalarıdır. Peki ya bizim senaryomuz şöyle oluşuyor olsaydı bu değişkenlerin değeri sadece aynı namespace dahilinde olan bir class tarafından değiştirilebilir. Yani PropertyAccessors isimli namespace haricinde bir yerden sadece okuma işlemi yapılacak olsaydı o zaman herkesin aklına farklı çözümler gelecekti ve kesinlikle bunu farklı yollar ile yapabilecektik. Örnek :

 

§          Değişkeni internal yaparım.

§          Bir metot hazırlarım internal olur sadece değişken değerini değiştirir vb

 

Fakat şöyle bir problem var ki property hala dışarıdan erişilebiliyor.

 

Peki çözüm ?

 

Çözüm olarak C# 2.0 ile birlikte eklenmiş olan özellikten faydalanacağız yani Property Accessor Modifiers.

 

Örnek :

 

    public class Ogrenci

    {

        int _yazilim;

        int _sistem;

 

        public int Yazilim

        {

            get { return _yazilim; }

            private set

            {

                if (value <= 100)

                    _yazilim = value;

            }

        }

        public int Sistem

        {

            get { return _sistem; }

            set

            {

                if (value <= 100)

                    _sistem = value;

            }

        }

    }

 

Sınıfımızı yukarıdaki şekilde hazırlarsak o zaman kullanılan yerler de bazı hatalar oluşacaktır.

 

 

 

Görüldüğü gibi Yazilim property artık değer kabul etmiyor. Sadece tanımlandığı class içerisinden deger kabul edecektir. En çok kullanım şekli tabi ki Set metotunun internal tanımlanması, get metotunun ise public olmasıdır.

 

    public class Ogrenci

    {

        int _yazilim;

        int _sistem;

 

        public int Yazilim

        {

            get { return _yazilim; }

            internal set

            {

                if (value <= 100)

                    _yazilim = value;

            }

        }

        public int Sistem

        {

            get { return _sistem; }

            internal set

            {

                this.Yazilim = 10;

                if (value <= 100)

                    _sistem = value;

            }

        }

    }

 

 

Şimdi gelelim her güzel konuda olduğu gibi kısıtlamalara. J

 

  • Hem get metotuna hem de set metotuna property accessor tanımlayamazsınız.
  • get veya set metotlarına vereceğiniz access modifier property nin erişim seviyesini geçemez. Hatta property erişim belirtecinden daha kısıtlı olmasını bekler derleyici.
  • Property accessor kullanabilmeniz için property nin hem get hem de set metotu tanımlanmalıdır. Biri bile yoksa bu özellikten faydalanamazsınız.

 

 

Böylece bir makalemizin daha sonuna geldik. Hepinize bir sonraki makalede görüşmek üzere iyi çalışmalar.

 

Sorularınız için mail adresim aşağıdadır.

bora.burgucugil@bilgeadam.com

BilgeAdam BTA Beşiktaş


Partial Types

                Visual Studio 2005 ile birlikte aslında hepimizin hayatına girmiş olan, birçoğumuzun ise hala farkında olmadığı yeni bir yapıdır partial types. Partial types sınıflarımızı (class), arayüzlerimizi (Interface) ve yapılarımızı (struct) partial anahtar kelimesi ile ayrı fiziksel dosyalarda tanımlayabilmemizi sağlayan yapıdır. ?Bu yapının bize sağladığı fayda nedir?? ?Neden bir class tanımlamasını ayırayım ki ?? Bunların cevabını açıklamadan önce şunu belirteyim Visual Studio 2005 kullanırken zaten istemeden hepimiz partial classlarla çalışıyoruz. Visual Studio 2005 içerisinde bir Windows Application açtığınızda karşınıza gelen Form1.cs ye baktığınızda göreceksiniz ki artık

 

public partial class Form1 : Form

 

şeklinde bir tanımlama söz konusu. Gelelim sorularımızın cevaplarına. ?Neden bir class?ı ayrı iki fiziksel dosya ya ayırayim ki ??. Eskiden beri her programcının baş belasıdır. Uzun ve karışık kodlar. Bunları aşmak için bazı standartlar var, okunabilirliği arttırma yönünde. Ama hepimiz biliyoruz ki, bir kod dosyası içerisindeki satır sayısı fazlalaştıkça okunabilirlik azalmakta. İşte bu yüzden Microsoft?unda tercih ettiği bir yöntem olan metotlar ile özelliklerin ve formdaki kontrollerin tanımlama bloklarını ayrı fiziksel dosyalara yazacağız. Yani formunuza yerleştirdiğiniz Button, Textbox vs. kontrollerin tanımı eskiden Windows Form Designer generated code olarak tanımlanan bir region içerisinde dururdu fakat artık ayrı bir dosya da duruyor. O dosyanın ismi de

Form1.Designer.cs. Bu kadar anlatımdan sonra biraz kodları görelim.

 

Eskiden (Visual Studio 2003) aşağıdaki gibi duran kodlar :

 

 

Artık Visual Studio 2005 içerisinde :

 

 

Şeklinde duruyor. Birde VS 2005 içerisinde ki solution explorer içerisine bakalım o zaman.

 

 

Resimde de gördüğümüz gibi VS 2005 içerisinde artık bizim Formlarımız artık en az 2 fiziksel dosya olarak açılmakta. Birinde bizim yazdığımız kodlar bulunacak. Diğerinde ise Visual Studio 2005 in bizim için oluşturduğu kodlar bulunacak. Birde Designer.cs uzantılı fiziksel dosyanın kodlarına bakalım.

 

 

Designer.cs uzantılı dosyada tutulan kodlar ise yukarıda ki şekilde görüldüğü üzere VS2003 te gördüğümüz her form için standart oluşturulan kodlar. Bunları gördükten sonra insanın aklına hemen e iki dosya varsa bunlar nasıl beraber çalışıyor gibi bir soru geliyor. Partial olarak işaretlenmiş fiziksel dosyalar derleyici için tek bir dosyaymış gibi işlem görürler. Daha açık konuşmak gerekirse. Bir class tanımladınız. Classın değişkenleri ve özellikleri bir fiziksel dosyada, class a ait metotlar bir dosyada dursun.

 

 

Yukarıdaki gibi bir class tanıtıyorum. Açılan classın kodlarına bi göz atalım.

 

 

görüldüğü üzere kodlarda bir fark görünmüyor. Şimdi hemen bir sınıf daha ekliyoruz.

 

 

Ekledikten sonra bir kere derliyoruz ve hatamızı görüyoruz.

 

 

Bu hatadan da gördüğümüz üzere classlarımızı tanımlarken partial anahtar kelimesini kullanmadık. Eğer class tanımlamalarımızı aşağıdaki şekilde değiştirirsek derleyici hatası almayacağız.

 

partialSinifim.Degislenler.cs

 

partialSinifim.Metotlar.cs :

 

 

O zaman anlıyoruz ki, bir sınıfı partial olarak işaretlemek istiyorsak tüm fiziksel dosyalarında class tanımlama satırına partial anahtar kelimesini yazıyoruz. Şimdi gelelim partial sınıfların bazı özelliklerine.

 

  • Partial olarak işaretlenen sınıflardan herhangi birinde class tanımlama satırında sealed, abstract, static şeklinde bir tanımlama var ise bunu tüm dosyalarda yazmak zorunda değilsiniz. Classlardan bir tanesine sealed yazsak dahi o classtan türeme yapamayacağız.

 

partialSinifim.Degiskenler.cs

 

 

partialSinifim.Metotlar.cs

 

 

Class1.cs :

 

 

Resimden de göreceğimiz gibi partialSinifim fiziksel dosyalarından sadece birinde sealed yazmamıza rağmen bu tanım tüm sınıf için geçerli oldu ve bu sınıftan türetme yapamaz hale geldik.

 

  • Partial anahtar kelimesi arayüzler(Interface) ve yapılar(struct) içinde kullanılabilir.

 

Bir makalemizin daha sonuna geldik. Bir sonraki makalemizde görüşene kadar herkese iyi çalışmalar.

 

Bora BURGUCUGİL

bora.burgucugil@bilgeadam.com

Bilge Adam Bilgi Teknolojileri Akademisi

Bireysel Yazılım Geliştirme Eğitmeni - Beşiktaş


Nullable Value Types

            Bu makalemizde .Net Framework 2.0 öncesinde ki ve .Net Framework 2.0 daki değer tipli değişkenlerin çalışma mantığındaki bir farklılıktan bahsediyor, örneklerle bu konunun inceliklerine değiniyor olacağız.

Tüm programcıların bildiği gibi değer tipli veri türleri yani sınıflarımız, nesnelerimiz ve string karakter katarı dışındaki tüm veri türleri değer tipliydi ve bu tipteki değişkenler null bilgisini taşıyamıyordu. Hatırlayacak olursak null değer taşımanın anlamı hiçbir nesneye ait  referans bilgisi taşımamasıydı. Bu konuyu biraz daha teknik olarak yorumlayacak olursak, değer tipli veri türleri oluşturulduklarında kendilerine STACK dediğimiz bölgeden yer alırlar ve bilgilerini kendi üzerlerinde taşırlar. Fakat referans tipli değişkenler bu durumdan biraz daha farklı olarak kendilerine taşınacak bilginin yer seçimi için HEAP dediğimiz bölgeyi seçerlerdi. Yani referans tipli nesnelerimiz HEAP bölgesinden kendilerine yer alıp referans bilgisini STACK içerisinde alacakları bölgeye yazarlardı. Bu yüzden onlara referans tipli diyorduk. Bu durumda referans tipli değişkenlerin null değer taşıması da anlamlandırılmış oluyordu. HEAP içerisinde hiçbir bölgeyi referans göstermemesi durumuna null değer taşıması da diyebiliyorduk. Bu bilgiler ışığında değer tipli veri türlerinin null değer taşıma gibi bir imkanı kalmamış oluyordu. Zaten bilgiyi kendi üzerinde taşıyan bir bölge söz konusu dolayısıyla bir referans söz konusu değil.

 

 

Yukarıda ki şekilde gördüğümüz integer tipten sayi1 isimli değişkene null bilgisi atayamayız. Atama yaptığımız takdirde derleme zamanında hata alırız.

 

Alacağımız hata ?Cannot convert null to ?int? because it is a value type? hatasıdır. Bunun anlamı null bilgi integer veri tipine çevrilemiyor çünkü integer değer tiplidir. (Hatanın tam Türkçesinin bu olmadığını bende biliyorum J anlamamız gereken bu ) Bu kodlardan da gördüğümüz gibi normal şartlar altında değer tipli bir değişkene null bilgisi yazamıyoruz. Peki referans tipli bir değişkene nasıl null bilgisi atıyoruz.

 

Not : burada snf instance için new yazmazsak yine snf null değerini taşıyacaktı fakat o zaman onu kullanmaya kalktığımda derleyici hatası alacaktık en azından ufak bir sahtekarlık ile derleyiciyi atlattık. J

 

Bu örnekteki snf isimli sınıf örneğimiz makale konusu olan null bilgiyide taşıyabilirler çünkü heap ile stack arasında bir referans ilişkisi olacaktır.

 

Artık değer tiplilerin neden null bilgisi taşıyamadığını bildiğimize göre asıl konumuza dönebiliriz. C# 2.0 içerisinde artık değer tipli değişkenlerimize de null bilgisini atayabiliyoruz. Nasıl yaptığımıza değinecek olursak :

 

Şekilde görüldüğü gibi herhangi bir değer türlü değişkene null bilgisi atayabilmek için değişkenin veri türünü belirttikten sonra ? karakterini ekliyoruz. Yani :

 

            Veri_türü? Değişken_adı;

Şeklinde bir tanımlama yaptığımız takdirde değer tipli değişkenlere de null değer ataması yapabiliyoruz. Bu tip bir kullanım nerede işime yarayacak dersek,  SQL Server  içerisinde her bir sütunumuzun ALLOW NULL isimli özelliğini vardı ve veri tipi ne olursa olsun database içerisinde her alana null değer atayabiliyorduk. İşte bu durumda örnek olarak datareader ile okuduğumuz herhangi bir tablodan null bilgisi dönüyorsa ve biz bu bilgiyi değer tipli bir değişkene atıyorsak runtime hatası alacağımız kaçınılmaz olur. Dolayısıyla ilk etapta bu tip sorunlardan kolayca kurtuluruz. Ayrıca kontrol yapmak zorunda kalmayız kısacası.

            Bu noktada gözden kaçırmamamız gereken ve bilmemiz gereken bir nokta daha var.

Null değer taşıyabilen değer tipli değişkenlerden, null değer taşıyabilir olarak işaretlenmemiş olan değer tipli değişkenlere bilinçsiz değer aktarımı yapılamayacağıdır.Ne demek istediğimizi yine örnek bir kodla açıklayalım.

 

 

Yukarıdaki şekilde de gördüğümüz gibi sayi1 isimli değişkenimizi null değer taşıyabilir olarak tanıttık fakat sayi2 isimli değişkenimizi bu yönde işaretlemedik. Bu yüzden yukarıdaki gibi bir atama söz konusu olduğunda ?Cannot implicitly convert type ?int?? to ?int?. An explicit conversion exists (are you missing a cast?)? şeklinde bir derleme zamanı hatası alıyoruz. Dolayısıyla null değer taşıyabilir şekilde işaretlediğimiz bir değer tipli değişkeni null değer taşıyabilir olarak işaretlenmemiş başka bir değişkene atanamaz. Atanması için bir şartın sağlanmış olması gerekmektedir. O şart da tür dönüşümüdür.

 

Not : yukarıdaki örnekte sayi1 = null yazan satırı sayi1 = 15 gibi uygun hale getirsenizde derleyici hatası alacaksınız. Dolayısıyla mutlaka çevirim yapılması gerekmektedir.

 

 

 

 

Yukarıda ki şekilde görüldüğü gibi sayi2 isimli null değer taşıyamaz olarak işaretlenmiş değişkene type casting ile artık sayi1 in değerinin atamasını yapabiliyoruz. Bu örnekte sayi1 null değer taşıdığı için runtime hatası alacağız o hatada

 

?Nullable object must have a value.? olacaktır. Bu örnekleri uç noktaları belli etmek için hazırladığım için hepsini görmenizi istedim. Peki şimdi bu tip bir sorunla bilerek karşılaşmıyorsak yani database içerisinden null bilgi döndü ise ve biz bunu nullable olarak işaretlediğimiz bir değişkene atadıysak daha sonra onu başka bir değer tipli değişkene atarken runtime hatası alacağız bunu nasıl çözeceğiz. Nullable değişkenlerin HasValue isminde bir property si var ve bu property bize bool tipten bir değer döndürüyor. Dolayısıyla bu tip bir atama yapılacağı zaman bu property kullanılabilir ve ortaya çıkabilecek olan hatalar engellenebilinir.

 

Şimdi bahsedeceğimiz başka bir konu ise nullable veri tipli değişkenlerin belirteci olan ? işaretinden yola çıkılarak oluşturulmuş bir operatör.

           

?? operatörü bizim için nullable değişkenler kullandığımızda işimizi çok kolaylaştıracak özelliklerini sunmaya başlıyor. Nasıl kullanılır ilk önce bunu açıklayalım isterseniz.

 

 

 

 

 

 

Yukarıdaki şekilde gördüğümüz gibi nullable bir değişken olan sayi1 den, null değer taşıyamayan sayi2 isimli başka bir değişkene değer aktarılmak isteniyor. Ama bunu şimdi farklı bir şekilde hallediyoruz. Tür dönüşümü kullanmadan hemde. Yukarıdaki kodda yapılan işlemin açıklaması ?: operatörüne benzer şekilde, eğer sayi1 isimli değişkenin değeri null değil ise sayi1 değerini sayi2 değişkenine aktar, şayet null ise sayi2 isimli değişken içerisine 0 değerini aktar. ?? operatörü tam olarak bu anlama gelmektedir. Eğer ?? operatörünün solundaki null değer taşıyabilir olarak işaretlenmiş değişken null değeri içermiyorsa onun değerini eşitliğin solundaki değişkene aktar, eğer null değer içeriyorsa ?? operatörünün sağındaki değeri eşitliğin solundaki değişkene aktar.

 

Nullable değer tipli veri türleri C# 2.0 ile birlikte hayatımıza girmeye başladı bile. Bunun yanında yakında C#2.0 ile ilgili birçok makale daha yayınlayacağız.

 

Bir sonraki makalede görüşmek üzere herkese iyi çalışmalar.


Refactoring

 

                Refactoring, Visual Studio 2005 ile birlikte hayatımıza getirilen pratikliklerden (veya kolaylıklardan da diyebiliriz) birisidir. Çok büyük yardımı yok gibi görünse de, proje geliştirirken birçok yeri ilgilendiren bir değişiklik yapmamıza olanak sağlar. Mesela bir kod bloğunu her sefer yazmak yerine bir metot yapmayı tercih edeceğimiz zaman,  bu ve bunun gibi detaylı şekilde inceleyeceğimiz, çok zaman alacak işlemler için Refactoring bize bir merkezi kontrol sistemi sağlıyor diyebiliriz.

 

                Şimdi Refactoring'in elemanlarını tanımaya başlayalım.

 

 

Ø Rename

Ø       Extract Method

Ø       Encapsulate Field

Ø       Extract Interface

Ø       Remove Parameters

 

 

RENAME :

 

                Refactoring? in Rename isimli elemanını kullanarak değişkenlerin (variables), metotların(methods),

sınıfların(classes), isim uzaylarının (namespaces), özelliklerin(properties) isimlerini kolayca değiştirebiliyoruz.

 

Kodumuzun şu şekilde olduğunu varsayalım ;

 

using System;

using System.Collections.Generic;

using System.Text;

 

namespace Refactoring_1

{

    class hesaplar

    {

        static int hesapID;

        public string hesapAdi;

        private decimal bakiye;

       

        public hesaplar(string hesapAdi, decimal bakiye)

        {

            hesapID += 1;

            this.hesapAdi = "";

            this.bakiye = 0;

        }

    }

}

 

Rename elemanını kullanabilmek için değiştirmek istediğimiz ismin üzerinde sağ klik yapıyoruz ve REFACTOR içerisinden RENAME menü öğesini seçiyoruz ve karşımıza yeni ismi isteyen bir dialog penceresi çıkıyor burada yeni ismi yazdıktan sonra alt tarafta bulunan checkbox lara bir göz atıyoruz.

 

 

İlk seçenek yani ?Preview reference changes? bu seçenek değişiklik gerçekleşmeden önce bize ufak bir pencerede değiştireceği yerleri gösteriyor. Böylece yanlış bir yeri değiştirme ihtimalimizi ortadan kaldırmış oluyoruz. Bu seçeneği pasif hale getirirsek bize bir ön izleme yapılmadan, tüm bulunan değerler, tüm proje içerisinde değiştirilecektir.

İkinci seçeneğimiz ?Search in comments?. Bu seçenek ise değiştirmek istediğimiz ismi, Visual Studio? nun geçersiz olarak işaretlenmiş ya da açıklama satırı olarak işaretlediğimiz yerlerde de araması için kullanılıyor.

                Üçüncü ve son seçeneğimiz ?Search in strings?. Bu seçeneğimiz ise seçtiğimiz ismin, proje içerisinde kullandığımız string ifadeler içerisinde de aranacağını veya aranmayacağını belirtiyor.

 

 

 

EXTRACT METHOD :

                Bir proje geliştirirken her programcının başına bela olan sorunlardan biridir kod tekrarı. Aynı kodu tekrar tekrar projenin ayrı yerlerinde yazmamak için metotları kullanırız. Metotlar C# dili içerisinde bir grup kod bloğunu çalıştırıp bize değer döndüren veya hiçbir şey yani void döndüren program parçacıklarıdır. Visual Studio 2005 metot tanımlamaları için Refactoring ile geliştiriciye bazı kolaylıklar sunmuş. Bunlardan biride Extract Method .

                Extract Method seçeneği bloklayarak seçtiğimiz bir grup kodu belirteceğimiz isme ve imzaya sahip bir metot haline getirmeye yarıyor. Bu seçeneğin biraz detaylarına girecek olursak :

 

                Extract method seçeneğini kullanabilmek için ilk önce metot haline dönüştüreceğimiz kod bloğunu seçiyoruz. Daha sonra bu seçili kod üzerinde sağ klik yapıp Refactor seçeneğinin üyelerinden Extract Method üyesini seçiyoruz ve işte her şey karşımızda. Visual Studio 2005 seçtiğimiz blok içerisindeki tanımlanmamış değişkenleri parametre haline getirip bizden sadece metota bir isim vermemizi bekliyor. Örnek olarak :

 

Basit bir toplama programı yazdığımız düşünelim girilen iki sayıyı toplayıp sonucu ekrana mesaj olarak gönderiyor.

 

 

 

private void button1_Click(object sender, EventArgs e)

        {

            int sayi1 = 0;

            int sayi2 = 0;

 

            sayi1 = Convert.ToInt32(textBox1.Text);

            sayi2 = Convert.ToInt32(textBox2.Text);

 

            int sonuc = 0;

 

            sonuc = sayi1 + sayi2;

 

            MessageBox.Show("Girilen iki sayının toplamı : " + sonuc);

        }

 

Bu kodu method haline getirmek istediğimizde bu kod bloğunu seçiyoruz. Daha sonra Extract Method üyesini seçiyoruz ve karşımıza yeni method ismini bekleyen bir dialog penceresi çıkıyor. Buraya yeni ismi verdikten sonra OK?e bastığımız anda projemizde verdiğimiz isim ile yeni bir method oluşturulacaktır. Visual Studio 2005

 

               

private void NewMethod(ref int sayi1, ref int sayi2)

 

 

bu şekilde bir method yaratacağını söyleyecektir. Verdiğimiz ismin de toplama olacağını varsayalım. Method

 

 

private void toplama(ref int sayi1, ref int sayi2)

 

 

 

halini alacaktır. Görüldüğü gibi blokladığımız kod içerisindeki sayi1 ve sayi2 değişkenleri tanımlanmadığı sadece kullanıldığı için onları ref anahtar kelimeli parametreler haline getirdi.bundan sonra bize sadece OK? e tıklamak kalıyor. OK? e tıkladığımız anda programımız içerisinde

 

 

        private void toplama(ref int sayi1, ref int sayi2)

        {

            sayi1 = Convert.ToInt32(textBox1.Text);

            sayi2 = Convert.ToInt32(textBox2.Text);

 

            int sonuc = 0;

 

            sonuc = sayi1 + sayi2;

 

            MessageBox.Show("Girilen iki sayının toplamı : " + sonuc);

        }

 

 

Şeklinde bir method oluşuyor ve bu kodu ilk yazdığımız ve seçtiğimiz yerde ise (class içerisinde) :

 

 

toplama(ref sayi1, ref sayi2);

 

 

 

şeklinde bir method çağırım satırı oluşuyor. Böylece extract method ile hem gereksiz kod tekrarından kurtulmuş, hem de daha kısa ve kolay şekilde istediğimiz kod bloğunu method haline getirmiş oluyoruz.

 

 

 

ENCAPSULATE FIELD :

                Yazdığımız her programda veya her class içerisinde kullandığımız değişkenlerin bazen sadece bizim yazdığımız class tarafından kullanılmasını isteyebiliriz. Ya da daha önceden yazdığımız bir class? ın bazı public değişkenlerinin dışarıdan direk erişilemez olmasını, bazı kontroller dahilinde değiştirilebilmesini isteyebiliriz Bu güvenlik daha doğrusu programın kontrollü ilerlemesi için önemli bir noktadır. Programımızda public olarak işaretlenmiş değişkenlere property aracılığı ile istediğimiz kullanım şartlarını yükleyebiliriz. Yani public olarak işaretlediğimiz bir değişkeni property haline getirirsek değişken tüm değer aktarımını property üzerinden yapacağı için Encapsulation işlemini gerçekleştirmiş oluruz. İşte Refactoring? in üyelerinden biri olan ENCAPSULATE FİELD ? da tam olarak bu işi yapmaktadır. Bizim seçtiğimiz bir değişkeni property haline getirmektedir. Bu da program içerisinde bize birçok yerde kolaylık sağlayacaktır. Örnek olarak :

 

 

  class hesaplar

    {

        static int hesapID;

        public string hesapAdi;

        public decimal bakiye;

 

        public hesaplar()

        {

            hesapID += 1;

            this.hesapAdi = "";

            this.bakiye = 0;

        }

    }

 

Şeklinde bir sınıfımızın olduğunu varsayalım.Bu sınıfta iki tane dışarıdan erişilebilir, public olarak işaretlediğimiz değişken tanımlı. Bu değişkenlere kullanıcı istediğini atayarak istediğini yapabilir. Bu programımızın bir sonraki versiyonunda bakiye isimli alanın biraz daha önem kazanması gerektiğini düşünüp, bu alana daha kontrollü bilgi aktarılması gerektiğini sağlamaya çalışıyoruz. Bu değişkenin bir property aracılığı ile kontrol edilmesi gerektiğine karar veriyoruz.Bunu yapmak içinde Refactoring? den yararlanıyoruz.