19 Eylül 2011 Pazartesi

C# Indexer Property

Indexer, özel bir tip property’dir. Yazıldığı sınıfa indexleyici özellik kazandırır. Dizilerde ve bazı koleksiyonlarda köşeli parantezler ile index verebilmemiz, bu property sayesindedir. İlk olarak Framework’de var olan ArrayList üzerinde inceleme yapalım, ardından kendi yazdığımız tiplere nasıl indeksleyici kazandırabileceğimizi inceleyeceğiz.

ArrayList tipinden bir nesne örnekleyerek içerisine eleman ekleyelim.

class Program

    {

        static void Main(string[] args)

        {

            ArrayList arrayList = new ArrayList();

            arrayList.Add("istanbul");

            arrayList.Add("ankara");

            arrayList.Add("izmir");

            arrayList.Add("bursa");

        }

    }

arrayList nesnesi üzerinden köşeli parantez açtığımızda,

Untitled

parametre olarak integer alan ve geriye object dönen bir üye söz konusu. Şimdi de ArrayList üzerinden Go to definition diyelim. Aşağıdaki görüntü ile karşılacağız.

Untitled

İşte gördüğümüz bu üye, ArrayList tipine indexer özelliğini kazandıran üyedir. get ve set bloklarından da anlaşılacağı gibi, bu üye bir property’dir. Ancak özel bir üyedir, adı “this” olmak zorundadır ve parametre almalıdır. Aşırı yüklenebilirler(overload edilebilir).

Kendi yazdığımız tiplerde indexer kullanabilmemiz için adı this olan ve parametre alan bu özel üyeyi eklememiz gerekmektedir. Şimdi Urun adında bir sınıf tasarlayalım, daha sonra da UrunYonetim adında bi sınıf tasarlayalım ve yapıcı metodunda bir Urun dizisi oluşturalım (ArrayList’in arka tarafta oluşturduğu object dizisi gibi). Oluşturduğumuz UrunYonetim sınıfının, içerisinde foreach ile gezilebilen bir tip olabilmesi için IEnumerable interface’ini implement edelim.

class Urun

    {

        public int Id { get; set; }

        public string Ad { get; set; }

        public double Fiyat { get; set; }

 

        public Urun(int id, string ad, double fiyat)

        {

            Id = id;

            Ad = ad;

            Fiyat = fiyat;

        }

    }

 

    class UrunYonetim : IEnumerable

    {

        public Urun[] UrunSepeti { get; set; }

 

        public UrunYonetim()

        {

            UrunSepeti = new Urun[]

            {

                new Urun(1,"Monitör",200),

                new Urun(2,"Klavye",80),

                new Urun(3,"Mouse",40)

            };

        }

 

        public IEnumerator GetEnumerator()

        {

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

                yield return UrunSepeti[i];

        }

    }

Indexer kullanımını sağlayan özel üyeyi bilmediğimizi varsayalım. UrunYonetim tipinden bir nesne örneklediğimizde indexleyici kullanmak istersek, aklımıza framework’de var olan ve indexer özelliği olan tipler gelir. Yani bir ArrayList nesnesi örnekleyerek, UrunYonetim içerisindeki diziyi bu nesne örneği ekleyebiliriz ve indeksleyici kullanabiliriz.

class Program

    {

        static void Main(string[] args)

        {

            UrunYonetim dukkan = new UrunYonetim();

 

            ArrayList arrayList = new ArrayList();

            foreach (Urun u in dukkan)

            {

                arrayList.Add(u);

            }

 

            Console.WriteLine(((Urun)arrayList[0]).Ad);

 

        }

    }

Burada iki dezavantajımız var. Birincisi, ram’e fazladan bir ArrayList örneği çıkararak iterasyon ile elemanları eklemek zorunda kaldık. Dolayısı ile ram’deki iş yükü artmış oldu. İkincisi de, arrayList indexleyici’si geriye object döndürdüğü için cast işlemi yapmak zorunda kaldık. Halbuki bizim UrunYonetim sınıfını yazmamızın amacı, arka tarafta bir Urun dizisi kapsüllemekti. Yani geriye bir Urun döneceğinden eminiz. İşte bu sebeplerden ötürü kendi sınıfımıza indexer özelliği kazandırmak yararımıza olacaktır. UrunYonetim sınıfına aşağıdaki üyeyi ekleyelim.

public Urun this[int index]

    {

        get { return UrunSepeti[index]; }

        set { UrunSepeti[index] = value; }

    }

Artık dukkan adlı nesne örneğine bir index verdiğimizde geriye, parametre olarak verilen index değerine sahip ürünü dönecektir.

class Program

    {

        static void Main(string[] args)

        {

            UrunYonetim dukkan = new UrunYonetim();

 

            //ArrayList arrayList = new ArrayList();

            //foreach (Urun u in dukkan)

            //{

            //    arrayList.Add(u);

            //}

 

            //Console.WriteLine(((Urun)arrayList[0]).Ad);

 

            Console.WriteLine(dukkan[0].Ad);

 

        }

    }

Untitled

Eklediğimiz üye sayesinde, yorum satırı olarak işaretlenen kısımda yapılan işlere gerek kalmadı. İndexer üyenin aşırı yüklenebilir olduğunu söylemiştik. Şimdi de parametre olarak string bir değer alan, ve girilen string ile aynı isme sahip ürünün fiyatını geriye döndüren bir üye yazalım. (Urun dizisi içerisindeki her bir ürünün adının unique olduğunu varsayalım.)

public double this[string name]

    {

        get

        {

            foreach (Urun u in UrunSepeti)

            {

                if (u.Ad.ToLower() == name.ToLower())

                {

                    return u.Fiyat;

                }

            }

 

            throw new IndexOutOfRangeException("ürün bulunamadı");

        }

    }

İsimleri karşılaştırırken, küçük-büyük harf sıkıntısı yaşamamak için ToLower() metodunu kullandık. Main metodu içerisinde,

Console.WriteLine(dukkan["monitör"]);

Untitled

Görüldüğü gibi, kendi yazdığımız tiplere indexer özelliğini kazandırmak son derece kolay. Faydalı olması dileği ile…



.Net’deki 5 temel tipten biri olan enum, bir değer aralığının tanımlandığı sayısal bir tiptir. Bir başka tanımla, sayıları kod içerisinde direk kullanmak yerine, isim vererek kullanmaktır. Değer türlü olduklarından ötürü ram’in stack bölgesinde yer alırlar. Gunler adında bir enum tanımlayalım;

enum Gunler

    {

        Pazartesi, Salı, Çarşamba, Perşembe, Cuma, Cumartesi, Pazar

    }

Yukarıdaki örneğe göre, pazartesi 0 değerini alır ve sonraki sabitlerin değeri de 1’er artarak devam eder. Tanımladığımız sabitlere sayısal bir değer verebilmemiz de mümkündür.

enum Gunler

    {

        Pazartesi = 1,

        Salı = 5,

        Çarşamba, // 6 değerini alacaktır

        Perşembe, // 7 değerini alacaktır

        Cuma = 141,

        Cumartesi, // 142 değerini alacaktır

        Pazar = 320

    }

Aksini belirtmediğimiz sürece içeride tutulan tüm değerler integer tipindedir. Ancak ihtiyacımıza göre, diğer tam sayısal tipleri de kullanabiliriz (byte, short, long)

enum Gunler : byte

    {

        Pazartesi, Salı, Çarşamba, Perşembe, Cuma, Cumartesi, Pazar

    }

Kod içerisinde ele alınış biçimleri ise,

Untitled

Şimdi küçük bir örnek ile enum sabitlerinin kullanımlarını incelemeye çalışalım. Ilk olarak Renkler adında bir enum tasarlayalım. Daha sonra da Urun adında bir sınıf tasarlayalım. Bu sınıfın  Id, Ad ve Renk adında 3 adet property’si olsun. Renk property’si Renkler tipinden olsun.

public enum Renkler : byte

    {

        Siyah, Beyaz, Sari, Kirmizi, Yesil, Mavi

    }

public class Urun

    {

        int _id;

        string _ad;

        Renkler _renk;

 

        public int Id

        {

            get { return _id; }

            set { _id = value; }

        }

 

        public string Ad

        {

            get { return _ad; }

            set { _ad = value; }

        }

 

        public Renkler Renk

        {

            get { return _renk; }

            set { _renk = value; }

        }

 

        public Urun(int id, string ad, Renkler renk)

        {

            Id = id;

            Ad = ad;

            Renk = renk;

        }

    }

Program tarafında bir Urun nesnesi örnekleyelim ve rengini ekrana yazdıralım.

public class Program

    {

        static void Main(string[] args)

        {

            Urun u = new Urun(1, "Monitör", Renkler.Siyah);

 

            Console.WriteLine(u.Renk.ToString());

        }

    }

Ekranda “Siyah” yazısını göreceğiz. Enum tipinin değer türlü olduğunu söylemiştik. O halde bu tipin sayısal karşılığını elde etmek veya kullanmak isteyebiliriz. Bunun için cast işlemi yapmamız gerekmektedir.

Urun u = new Urun(1, "Monitör", Renkler.Siyah);

Console.WriteLine((byte)u.Renk);

Yukarıdaki kod çalıştığında ekranda “0” yazdığını göreceğiz. Eğer ürünün rengi “Sari” olsaydı, ekranda “2” yazdığını görecektik. Çünkü enum sabitleri birer artarak değer alırlar (aksini belirtmediğimiz sürece). Siyah=0, Beyaz=1, Sari=2… şeklinde devam edecektir.

Şimdi de string bir değerin Enum tipine nasıl dönüştürüleceğini inceleyelim. Kullanıcıdan bir renk girmesini isteyelim ve bu rengi , yeni tasarladığımız ürünün rengine atayalım. Bu dönüştürme işlemi için Enum sınıfının static olan “Parse” metodunu kullanacağız. İlk parametre, dönüştüreceğimiz Enum tipi, ikinci parametre ise dönüştürülecek string değerdir. Üçüncü parametre ise küçük-büyük harf duyarlılğını belirtebileceğimiz boolean bir değer alır.(2.kullanım). Parse metodu geriye objcet döndüğünden cast işlemi de yapmamız gerekecektir.

public class Program

    {

        static void Main(string[] args)

        {

            Console.Write("Bir renk giriniz: ");

            string renkBilgisi = Console.ReadLine();

 

            if (Enum.IsDefined(typeof(Renkler), renkBilgisi))

            {

                Renkler girilenRenk = (Renkler)Enum.Parse(typeof(Renkler), renkBilgisi);

                Urun u2 = new Urun(2, "Klavye", girilenRenk);

                Console.WriteLine("Urun adı: {0} , Urun rengi: {1}", u2.Ad, u2.Renk.ToString());

            }

            else

            {

                Console.WriteLine("Böyle bir renk tanımlı değil");

            }

 

        }

    }

IsDefined metodu, girilen değerin Enum tipi içerisinde tanımlı olup olmadığını kontrol eder.

Untitled

Girdiğimiz renk bilgisi, Renkler içerisinde mevcut değil ise,

Untitled



16 Eylül 2011 Cuma

Asp.net IIS Problem

Geliştirdiğimiz bir projeyi local’imizde iis içerisine atmak isteyebiliriz. Bu işlemi, Internet Information Service içerisindeki Default Web Site altına tanımlayarak gerçekleştirebiliriz. Gelişmiş ayarları yaparken “Application Pool" içerisine, uygulamamızın yazılmış olduğu framework versiyonunu göremiyorsak (örneğin, ASP.NET v4), Visual Studio Command Prompt açarak aşağıdaki komutu çalıştırmamız yeterli olacaktır.

aspnet_regiis -i



6 Eylül 2011 Salı

C# yield Operatörü

Bir önceki makalemizde foreach iterasyonu sırasında arka planda ne gibi işlemlerin yapıldığını ayrıntısı ile incelemiştik. foreach iterasyonunun yapılmasına olanak sağlayan interface IEnumerable'dır. Bu interface, uygulandığı sınıfa GetEnumerator adlı bir metot kazandırır ve bu metot geriye IEnumerator interface’ini implement eden bir sınıf döndürür. İşte yield operatörü burada devreye girmektedir ve bir önceki örnekte yazdığımız Numerator sınıfını yazmaktan bizi kurtarır. Örneğimiz bir önceki makalemiz ile aynı olacak. Sadece son adımdaki Numerator sınıfını yazmayacağız.

class Urun

    {

        private int _id;

        private string _ad;

        private double _fiyat;

 

        public int Id

        {

            get { return _id; }

            set { _id = value; }

        }

 

        public string Ad

        {

            get { return _ad; }

            set { _ad = value; }

        }

 

        public double Fiyat

        {

            get { return _fiyat; }

            set { _fiyat = value; }

        }

 

        public Urun(int id, string ad, double fiyat)

        {

            Id = id;

            Ad = ad;

            Fiyat = fiyat;

        }

    }

class Dukkan : IEnumerable

    {

        private Urun[] _urunSepeti;

 

        public Urun[] UrunSepeti

        {

            get { return _urunSepeti; }

            set { _urunSepeti = value; }

        }

 

        private Urun[] UrunleriGetir()

        {

            return new Urun[]

            {

                new Urun(1, "Monitor", 200),

                new Urun(2, "Klavye", 80),

                new Urun(3, "Mouse", 40)

            };

 

        }

 

        public Dukkan()

        {

            UrunSepeti = UrunleriGetir();

        }

 

        public IEnumerator GetEnumerator()

        {

            throw new NotImplementedException();

        }

    }

işte bu aşamadan sonra işimiz gayet kolay. yield operatörü sayesinde, bizim için yazması zahmetli olan Numerator sınıfını yazmamıza gerek kalmadı. Şimdi, GetEnumerator metodunun içini aşağıdaki gibi değiştirelim.

public IEnumerator GetEnumerator()

        {

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

                yield return UrunSepeti[i];

        }

Burada return edilen ifade, IEnumerator interface’i ile gelen Current property’sinde return edilen ifade ile aynıdır. Artık Dukkan tipinden bir nesne içerisinde foreach ile iterasyon yapabiliriz.

class Program

    {

        static void Main(string[] args)

        {

            Dukkan urunler = new Dukkan();

 

            foreach (Urun urn in urunler)

            {

                Console.WriteLine(urn.Ad);

            }           

        }

    }

Alacağımız ekran görüntüsü bir önceki örnek ile aynı olacaktır.

Untitled

Bu örnekte yield operatörü yardımı ile, Numerator sınıfına gerek kalmadan kolay bir şekilde iterasyon yapabildğimizi görmüş olduk. yield operatörü, bizim için  gerekli olan Numerator sınıfını otomatik olarak oluşturmaktadır.

Faydalı olması dileğiyle…