Bu site emekli olmuştur. Arşiv amaçlı olarak BT AKADEMİ sponsorluğunda yayın hayatına devam etmektedir.




C#nedir?com
 
YAZAR HAKKINDA
Sefer Algan
Sefer Algan
http://www.seferalgan.com
İletişme geçmek için tıklayın.
71 Makalesi yayınlanmakta.
Yazar hakkında detaylı bilgi için tıklayın.
Yayınlanan diğer makaleleri için tıklayın.
İlgili etiketler: aslinda derleyici detayli eklenen genisletme herhangi ilgili isimsiz kullanim lambda metotlar static string tamamen yukaridaki .NET 3.x Sefer Algan
 
YAZI HAKKINDA
Türü : Makale
Serbest Köşede C#nedir?com üyelerinin hazırladıkları yazılar yayınlanır. Bu yazılar editör incelemesine girmeden yayınlanır.
Seviyesi : İleri
Kategori : .NET 3.x
Yayınlanma Tarihi : 7.7.2006
Okunma Sayısı : 65590
Yorum Sayısı : 8     yorum yaz
Site İçi AramaSİTE İÇİ ARAMA
Üye Girişini AçÜye GİRİŞİ
Üye girişi için tıklayın.
Kullanıcı Adı
Şifre
 
Beni her zaman hatırla
Bir hafta boyunca kullanıcı bilgilerinizi kullanıcı çıkışı yapana kadar hatırlar. (Paylaşılan bilgisayarlarda önerilmez.)
 
Şifremi / Kullanıcı Adımı unuttum.
 
.net TV RSS Serbest KÖŞE (?)
Serbest Köşede C#nedir?com üyelerinin hazırladıkları yazılar yayınlanır. Bu yazılar editör incelemesine girmeden yayınlanır.
emre TAŞ
Silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
Makale Gönder Bende Yazmak İstiyorum
.net TV RSSBlogroll
Turhal Temizer
Conda install environment.yml Package 23.11.2024
Turhal Temizer
Mac OS/X Removing CUDA 23.11.2024
Burak Selim Şenyurt
Rust ile ECS Yaklaşımını Anlamak 23.11.2024
Burak Selim Şenyurt
Birlikte Rust Öğrenelim Serisi 23.11.2024
  Diğer Herşey
Sponsorlar
BT Akademi
Medya Portakal
Video Hosting Sponsoru
Csharpnedir.com bir Ineta üyesidir
Uzman Abi
Her Yönüyle C# - Sefer Algan
C# 3.0 : Dil Yenilikleri ve LINQ (Language Integrated Query)
 
Kapat
Sayfayı Yazdır Sık Kullanılanlara Ekle Arkadaşıma Gönder MySpace Del.Ico.Us Digg Facebook Google Mixx Reddit StumbleUpon
Bu iki makaleden oluşan dizide sizlere C# 3,0’ın biz programcılara ne gibi yenilikler getirmeye çalıştığından bahsedeceğim. Makaleme başlamadan önce hepinizin kafasında oluşabilecek muhtemel sorulara cevap vermek istiyorum. Henüz daha C# 2.0’a alışmadan ve C# 2.0’ın getirdiği yenilikleri hazmetmeden C# 3.0 ’dan bahsediyor olmak aslında Microsoft’un C# diline ne kadar önem verdiğini göstermektedir. Programcıların sıkça kullandığı yapılardan ve günümüzde yoğun kullanılan programatik deyimlerden yola çıkarak kod yazmayı ve üretkenliği artıracak yeni dil eklentilerinin C#’a eklenmesi kimileri tarafından olumsuz bir şekilde eleştirilsede ben olumlu karşılıyorum. C# dili genel amaçlı bir programlama dili olmasına rağmen günümüzdeki kullanım alanı ile ilgili yapılan araştırmalara göre büyük bir kesimin C# dilini veri merkezli (data centric) uygulamaları tasarlamak için kullandığı görülmüştür. Yani hemen hemen her C# uygulamasında bir veri kaynağı bulunmakta ve bu veriler anlamlı hale getirilerek işlenmekte. Hatta yakın bir zamanda şahit olduğum bir olayı anlatmak istiyorum. 2005 yılında Amerika’da C# dilinin mimarlarından olan Anders Hejlsberg’in bir sunumuna katılmıştım. Sunum tabiki C# 3.0 ile ilgiliydi. Hejlsberg katılımcılara "Kaç kişi geliştirdiği herhangi bir uygulamasında herhangi bir veritabanı kullandı?" sorusunu yöneltti. Katılımcılara soru anlamsız! geldiğinden olsa gerek önce soru anlaşılmadı. Hejslberg soruyu tekrarlayınca herkesin eli havadaydı. Hejslberg, işte bu yüzden C# 3.0’a birazdan anlatacağım yenilikleri ekledik dedi ve sunumuna devam etti. İstatistikler ve gerçekler gösteriyorki .NET paltfomu daha çok veri merkezli uygulamalarda kullanılıyor. Bu yüzden .NET platformunun yaygın kullanılan bu amacına yönelik olarak .NET dillerininde üretkenliklerini artıracak yeni özelliklerin eklenmesi kaçınılmaz hale gelmiştir.

Günümüzde en çok veri kaynağı olarak veritabanı sistemleri kullanılmaktadır. Genel amaçlı bir programlama dilinden (mesela C#, VB.NET, C++ ) beklediklerimiz ile veritabanı sistemlerinden beklediklerimiz arasında tam bir uyumdan bahsetmek mümkün değildir. Söz gelimi C# ve SQL Server dan bir örnek vermek gerekirse, C# dilinde int türünden bir veri değişkeni null değer içeremezken aynı veri tipinin SQL Server’daki karşılığı olan tip null değer içerebilmektedir. Bu yüzden genel amaçlı bir programlama dili ile özel amaçlı bir geliştirme yapmanın ekstra efor gerektirdiğini söylemek sanırım yanlış olmayacaktır. Bu tür durumları gidermek için programlama diline yapılan eklentiler o dilin zamanla genel amaçlı dil olmasından çıkarabileceği için yeni eklenen özelliklerin dikkatle ve özenle seçilmesi gerekiyor. Bu amaçla C# 2.0 ’da null değer alabilen temel değer tipleri kavramı eklenmiştir. Bu özellik aynı zamanda generics altyapısı ile desteklendiği için dilin genel amaçlı olma özelliği kaybolmamıştır.

C# 3.0’a eklenmesi öngörülen yeni özelliklerinde yine bu amaca yönelik olduğu açıkca gözükmektedir. Yani birazdan detaylı olarak ele alacağım C# 3.0 yeniliklerinin hemen hemen tamamı veri merkezli uygulamaların daha hızlı geliştirlmesi için gereken yapıları desteklemek amacıyla eklenmiştir. Bu yüzden C# diline yeni eklenecek olan özellikleri öncelikli olarak geliştirilme amaçlarına yönelik irdeleyeceğiz.

C# 3.0 ve LINQ (Language Untegrated Query) nedir?

C# 3.0 ilk olarak 2005 yılındaki PDC (Professional Developer Conference) etkinliğinde duyruldu. C# 3.0 daki yeni özellikler ilk olarak LINQ (Language Integrated Query) adı verilen bir proje ile anılmaya başlandı. LINQ projesi C# diline entegre olmuş hafızadaki veya harici bir kaynaktaki verileri hızlı ve efektif bir şekilde sorgulayabilecek yapılara verilen bir takma isimdir. C# 3.0 daki yeniliklerin şimdilik tamamı LINQ projesinin altyapısını oluşturmaktadır. Bu makalede sizlere C# 3.0 daki dil yeniliklerinden ve sonrasında ise LINQ projesinin kapsamından bahsedeceğim.

C# 3.0 ın yeniliklerini kısıtlı da olsa derleyebilen bir derleyici PDC’de yayınlanmıştı. Bu derleyici VS.NET 2005 ile entegre çalışabilmektedir. PDC olduğu sıralarda Visual Studio.NET 2005 beta aşamasında olduğundan daha sonra final sürümü için başka bir kurulum hazırladılar. LINQ Preview olarak adlandırılan bu kurulum derleyiciyi ve VS.NET eklentilerini barındırıyor. İndirmek için aşağıdaki bağlantıya tıklayabilirsiniz.

Visual Studio.NET 2005 Final Sürümü için LINQ Preview kurulum dosyaları

Kurulumu yaptıktan sonra Visual Studio.NET 2005 editöründe aşağıdaki gibi bir eklentinin yapıldığını göreceksiniz. Bu proje tiplerinden birini seçtiğinizde LINQ için gerekli olan kütüphaneler otomatik olarak referans edilecek ve "Build" işlemini gerçekleştirdiğinizde C# 3.0 derleyicisi otomatik olarak çalıştırılacaktır.



LINQ yapıları ve C# 3.0 daki dil yeniliklerinin son hali kod adı "Orcas" olan ve şu anda çıkma tarihi kesin belli olmayan (tahminen 2007’nin sonu yada 2008’in başı )Visual Studio.NET versiyonu ile belirlenecektir. Dolayısıyla birazdan detaylı olarak ele alacğım C# 3.0 dil yeniliklerinin 2 sene içerisinde çok fazla değişime uğrayacağını söyleyebiliriz. Nitekim şu anda yayımlanan versiyon, Anders Hejlsberg’in de dediği gibi bir nabız yoklamadır.

En çok merak edilen konulardan bir tanesi de C Omega ile C# 3.0 ’ın aralarındaki ilişki. Öncelikle C Omega’nın Microsoft Research bünyesinde gerçekleştirilen bir araştırma projesi olduğunu söylemek gerekir. Dolayısıyla C Omega ile C# 3.0 arasında direkt bir ilişkiden bahsetmek mümkün değildir. Her iki ekipte birbirlerinden tamamen bağımsız çalışmaktadır. C Omega ekibi deneme yanılma yolu ile yenilikler üreterek C# dilini geliştiren ekibe yardımcı olmakta. Kısacası C Omega dili tamamen ayrı bir uzayda değerlendirilmelidir. C Omega’nın Microsoft’un herhangi bir ürününde yer alması yada ayrıca pazarlanması düşünülmemektedir.

C Omega hakkında detaylı bilgi almak için tıklayınız.

C# 3.0 Dil Yenilikleri

Bu bölümde C# 3.0 ’a eklenmiş olan yeniliklerden detaylı bir şekilde bahsedeceğim. Bolum sonunda daha detaylı bilgi için çeşitli bağlantılar da vereceğim. Yukarıda da söylediğim gibi dile eklenen özelliklerin tamamı LINQ yapılarını desteklemek amıcıyla eklenmiştir. Ve elbetteki bir çok özellik C# 2.0’daki yeniliklerin üzerine inşa edilmiştir. Burada bahsedeceğim bir çok yeniliği anlayabilmeniz için C# 2.0 daki yenilikleri biliyor olmanız gerekir. C#nedir?com’da C# 2.0 ile ilgili yayınlanmış bir çok makale var. Öncelikle onları okumanızı tavsiye ediyorum.

1 - Bilinçsizce türlendirilmiş yerel değişken tanımlama (Implicitly typed local variables)

Birgün mutlaka olmasını istediğim bir özellikti bu. İlk duyduğumda çok sevinmiştim. C# 3.0 da değişkenleri tanımlarkan artık tiplerini vermek zorunda değiliz. Dile eklenen "var" isimli bir anahtar sözcükle değişkenleri tanımlamak mümkün hale gelmiştir. Değişkenin tipinin ne olacağına o değişkene atanan ilk değer ile karar verilmektedir. Örneğin aşağıdaki kullanımlar tamamen geçerli olmaktadır.

var a = 5;
var b = true;
var s = "sefer algan";
var p = new Personel(); //Personel sınıfımızın oldugunu varsayıyorum.

İlk akla gelen soru bu tanımlama şeklinden performansın ne şekilde etkileneceği? Cevabı çok basit: değişen hiç birşey yok. Çünkü bu kullanım javascript’te bulunan var yada eski VB 6 da bulunan var(variable) tanımlama biçimlerinden tamamen farklıdır. Derleyici var ile bildirilen değişkenlere atanan ilk değerlere bakarak değişkenin tipine karar verir ve ürettiği kodu ona göre belirler. Yani yukarıdaki kod blokları ile aşağıdaki kod bloklarının IL seviyesinde hiç bir farklılığı yoktur. Dolayısıyla bu değişiklik performansı hiç bir şekilde etkilemeyecektir.

int a = 5;
bool b = true;
string s = "sefer algan";
Personel p = new Personel(); //Personel sınıfımızın oldugunu varsayıyorum.


var ile object tanımlamayı karıştırmamak gerekir. object bir referans tipidir ve bellekte belirli bir yer kaplar. Kendisine atanan değişkenler değer tipleri ise boxing ve unboxing işlemi gerçekleşir ki bu da performans düşmesine neden olur. Ancak var bir veri tipi değildir sadece bir değişken bildirme biçimidir.

var bildirim şekli daha sonra bahsedeceğim isimsiz tipleri(anonymous types) desteklemek amacıyla dile eklenmiştir.

var ile bildirilen değişkenlerin tipleri derleme zamanında belirlendiği için aşağıdaki kullanım tamamen geçersizdir. Aşağıdaki geçersiz kullanım var ve object arasındaki farklı sanırım açıklayacaktır.

var a = 7;
a= "s"; // geçersiz atama cunku a derleyici tarafından int olarak belirlendi.

//Diğer hatalı durumlar
var a; // ilk değer verilmek zorunda
var b = null; // tip belli olmadığından null değer alamaz



var deyiminin bir kullanım alanıda karışık ve yazılması zor olan veri tiplerini kısa bir şekilde tanımlamak. Örneğin aşağıdaki gibi generic bir hashtable koleksiyonu tanımlanabilir.

Dictionary<Personel, List<int>> puanlar = new Dictionary<Personel, List<int>>;

// yerine

var puanlar = new Dictionary<Personel, List<int>>;


2 - Nesnelere ve koleksiyonlara ilk değer ataması (Object and Collection Initializers) Nesneleri yaratırken yapıcı metotlar yardımıyla nesnelerin özelliklerini belirleriz. Farklı amaçlarla çeşitli şekillerde aşırı yüklenmiş yapıcı metotlar yazmak zorunda kalıyoruz çoğu zaman. C# 3.0’a eklenen bir yapı ile birlikte artık işlevi sadece özelliklerini atamak olan yapıcı metotlar yazmamıza gerek kalmayacak. Çünkü nesneyi yada koleksiyonu tanımladığımız anda nesnesinin özelliklerini verebiliyoruz. Buna göre aşağıdaki kullanım artık tamamen geçerlidir.

public class Personel
{
       public int No;
       public string Ad;
       public Maas maas;
}

public class Maas
{
       public int Tutar;
       public string Kur;
}

static void Main()
{
       var alininMaasi = new Maas{Tutar=1000, Kur ="USD"};

       var ali = new Personel{No=12, Ad="Ali Aslan",maas = alininMaasi }

       //yada

       Personel veli = new Personel{No=12, Ad="Veli Aslan",maas = new Maas{Tutar=200,Kur="YTL"} }
}



Nesnelere ilk atama yapmak dışında bu yapı kullılarak koleksiyonlarada başlangıç değerleri verilebilmektedir. Bunun için koleksiyonun mutlaka System.Collections.Generic isim alanında bulunan ICollection<T> arayüzünü uygulaması gerekmektedir. AŞağıdaki gibi bir tanımlama yapıldığı anda ICollaction<T>.Add(T eleman) isimli metot her bir eleman için otomatik olarak çağrılmaktadır.

List<string> isimler = new List<string> {"ali","veli","sefer","oguz","burak","mustafa"};


3 - İsimsiz Veri Tipleri (Anonymous Types)

C# 2.0 da isimsiz metotlar yeniliği vardı hatırlarsanız. Şu anda ise isimsiz veri tipleri ile karşı karşıyayız. Öyle bir veri tipi düşünün ki adı yok. Peki adı yoksa bu veri tipini nasıl oluşturacağız ve bu tipten bir nesne nasıl yaratacağız. Cevabını tahmin ediyor olmanız lazım: elbette ki var deyimi ile. Bir değişkenin hangi veri tipi modelinde olacağı artık değişkenin tanımlandığı noktada yapılabilmektedir. Ancak değişkenin tipi belli olmadığı için mecburen var ile tanımlamak zorundayız. Bu yapıyı JavaScript dilini bilinler anımsayacaktır. Buna göre 3 elemandan oluşan bir Personel veri yapısı aşağıdaki gibi basitçe tanımlanabilmektedir.

var veli = new {No=12, Ad="Veli Aslan"}

Console.WriteLine( veli.No.ToString());
Console.WriteLine( veli.Ad);

var ali = new {No=3, Ad="Ali Aslan"}

ali = veli // bu atama geçerlidir cunku isimsiz tipler aslında IL de aynı tipe denk düşer.

var veli2 = new {ali.No,ali.Ad}; // şeklinde de tanımlama yapılabilir. Boylece veli değişkeni otomatik olarak ali değişlenin tipinde olacaktır.


Yukarıdaki gibi isimsiz tip tanımlaması yapıldığında C# derleyicisi otomatik olarak bir int birde string property ve field içeren bir sınıf yaratıp IL kodunun içine gömecektir. Böylece ismini bilmesekte kullanabildiğimiz bir veri yapısı olacaktır.

4 - Genişletme Metotları (Extension Methods)

Genişletme metotları derlenmiş yada kod içerisinde bulunan herhangi bir veri tipini yeni metotlarla genişletme amacıyla eklenmiştir. Örneğin kendimiz bir genişletme metotdu yazarak string sınıfına yeni bir metot tanımlayabiliriz. Hatta object metoduna yeni bir extension metot bile yazabiliriz. Boylece her türlü nesnede bizim yazdığımız metot otomatik olarak görülecektir. Genişletme metotlatrınında yine LINQ kapsamındaki sorgu ifadelerini desteklemek amacıyla yapıldığını birazdan göreceksiniz. Ancak her ne kadar LINQ için konulmuş bir özellik olsada yapı esnek tutulmuş ve herhangi bir tip için genişletme metodu tanımlayabileceğimiz halde tasarlanmıştır.

Söz gelimi string sınıfı için ToInt32 adı ile yeni bir metot tanımlayabiliriz. Boylece string değişkenlerini tam sayıya dönüştürmek için Convert.ToInt32 metodunu kullanmamıza gerek kalmayacak. Yada kendi ihtiyaçlarınıza özel olarak string sınıfına farklı farklı metotlar ekleyebilirsiniz.

Genişletme metotları ile ilgili bilmemiz gereken en önemli kural metodun mutlaka statik bir sınıf içerisinde statik olarak tanımlanması gerektiğidir. (Statik sınıflar C# 2.0 a eklenen yeni bir özelliktir). Statik sınıflarla ilgili Burak Selim Şenyurt’un detaylı bir makalesini sitemizden bulabilirsiniz.) Genişletme metotlarının ilk parametresi hangi veri tipi ile ilgili ise this anahtar sözcüğü ile belirtimelidir. Aşağıda ornek bir genişletme metodu görmektesiniz.

namespace ExtensionMethods
{
      public static class MyExtensions
      {
            public static int ToInt32(this string str)
            {
                  return Int32.Parse(str);
            }
      }
}


Yukarıdaki sınıf bildiriminden sonra using ExtensionMethods; denilen her yerde kullanılan string tipindeki değişkenlerde ToInt32 isimli metot yer alacaktır. Gördüğünüz gibi string sınıfında gerçekte olmayan bir metot varmış gibi davranıyor derleyici. Bu bildirimlerden sonra aşağıdaki kod tamamen geçerli olacaktır.

using ExtensionMethods;
class Program
{
      public static void Main
      {
               string str = "35";
               int a = str.ToInt32();
      }
}


Genişletme metotlarının bildiriminde bulunan ve this öneki alan parametre genişletmek istediğimiz tipi ve metoda gönderilecek olan parametre değişkeninmi temsil etmektedir. Dolayısıyla yukarıdaki örnekte görüldüğü üzere str isimli değişken sanki metodun parametresiymiş gibi davranıyor. Birden fazla parametresi olan genişletme metotlarıda tanımlamak mümkündür. İlk parametre dışındakileri normal bildiğimiz şekilde tanımlanmaktadır. Örneğin string sınıfının Substring metodunun sondan başlayacak şekilde düzenleyip adını EndSubstring() şeklinde bildirebiliriz. Örneğin str.EndSubstring(4); dediğimizde sondan itibaren 4 karakterlik alt bolumu geri donecektir. Böyle bir metot aşağıdaki gibi tanımlanabilir.

namespace ExtensionMethods
{
      public static class MyExtensions
      {
            public static string EndSubstring(this string str,int count)
            {
                  return str.Substring(str.Length- count, 4);
            }
      }
}


Genişletme metotlarının metot aşırı yükleme ve yansıma(reflection) gibi konularda nasıl davranacağı ile ilgili henüz net bir bilgi bulunmamaktadır. Bütün bunların cevabını ilerleyen zamanlarda öğreneceğiz.

Önemle vurgulanması gereken konu genişletme metotları kalıtım yolu ile türetmeye bir alternatif olarak gelmemiştir. Buradaki amaç tamamen LINQ projesini desteklemek olduğu için klasik türetme mantığını korumamızda fayda var. Genişletme metotları gibi ileriki zamanlarda genişletme özellikleri, olayları ve operator metotlarınında olacağı söylenmekte. Ancak şu andaki derleyici bu tür yapıları desteklememektedir.

5 - Lambda İfadeleri (Lambda Expressions)

Lambda ifadeleri Pyhton, Lisp ve Schema gibi bir çok programlama dilinde öteden beri olan yapılardır. Güçlü yapısı sayesinde çok karışık algoritmaları kolay bir şekilde ifade edebilmemize yarıyor. Bir dilde olmazsa olmaz yapılardan olmasada programcıya büyük kolaylık sağlamaktadır. Lambda ifadelerini aynı örneğin C# 1.1, C# 2.0 ve C# 3.0 versiyonlarını yaparak daha rahat anlayabiliriz. Örneğimizi C# 2.0 ile birlikte gelen List<T> generic sınıfından yola çıkarak yapacağız. C# 1.1 de Generic sınıflar yer almadığından C# 1.1 için vereceğim örnek elbetteki 1.1 derleyicisi ile derlenemeyecektir. C# 1.1 örneğini yine C# 2.0 ile derleyeceğiz ama C# 2.0’daki isimsiz metotların(anonymous method) olmadığını varsayacağız.

List<int> sınıfı yapısında int türünden değişkenleri saklayabilmekteyiz. Tanımlayacağımız bu koleksiyon üzerinden arama yapabilmek için List<T> sınıfı içerisinde FindAll() isimli bir metot yer almaktadır. FinAll fonksiyonunun prototipi aşağıdaki gibidir.

using System.Collections.Generic;

public class List<T>
{
      public List<T> FindAll(Predicate<T> match)
      {... }
}

public delegate bool Predicate(T val);


Yukarıdaki kod blokları C# 2.0 ile birlikte gelen List sınıfı ve Predicate isimli temsilcinin bildirimlerini içermektedir. FindAll metodunun amacı varolan bir koleksiyondan istediğimiz koşulları sağlayan alt bir kümeyi bulmak ve geriye döndürmektir. Buradaki soru işareti kriterlerin nasıl verileceğidir? C# 1.1 de olsaydık yapabileceğimiz şey Predicate temsilcisine uygun bir metot ile koşulları test edip geri döndürmektir. FindAll metodu kendi içinde her bir eleman için Predicate ile temsil eden metodu (bizim yazdığımız metot) çağırarak kritere uyup uymadığını kontrol eder. Metodun geri dönüş değer bool olduğundan true dönen değerleri kritere uygun kabul eder ve alt koleksiyona ekler. Boylece istediğimiz kriterlere gore alt bir List<int> kümesi elde etmiş oluruz. Eğer C# 2.0 da isimsiz metotlar olmasaydı bu işlemi C# 1.1 mantığıyla aşağıdaki gibi oluşturmamız gerekirdi.

- C# 1.1 Mantığı
static void Main()
{
       List<int> sayilar = new List<int>();
       sayilar.Add(1);
       sayilar.Add(2);
       sayilar.Add(3);
       sayilar.Add(4);
       sayilar.Add(5);
       sayilar.Add(6);

       Predicate<int> f = new Predicate<int>(KararVer);
       List<int> ciftSayilar = sayilar.FindAll(f);

       foreach (int i in ciftSayilar)
       {
              Console.WriteLine(i);
       }
}

static bool KararVer(int deger)
{
         return deger % 2 == 0;
}



Örneği çalıştırdığınızda ekrana 2,4,6 yazdığı görülecektir.

C# 2.0 da yukarıdaki örneği isimsiz metotları(anonymous methods) kullanarak daha sade bir şekilde çözebiliyoruz. İsimsiz metotlar parametre olarak bir temsilcisi nesnesi bekleyen durumlarda da kullanılabildiği için yukarıdaki örneği C# 2.0 da KararVer gibi bir metot tanımlamadan aşağıdaki gibi şekillendirebiliyoruz.

- C# 2.0 Mantığı
static void Main()
{
       List<int> sayilar = new List<int>();
       sayilar.Add(1);
       sayilar.Add(2);
       sayilar.Add(3);
       sayilar.Add(4);
       sayilar.Add(5);
       sayilar.Add(6);

       List<int> ciftSayilar = sayilar.FindAll( delegate(int val) {return val%2==0;} );

       foreach (int i in ciftSayilar)
       {
              Console.WriteLine(i);
       }
}



Yukarıdaki orneği çalıştırdığımızda yine aynı sonuc aldığımızı görürüz. İsimsiz metotlar sayesinde temsilci bekleyen bir parametreyi metot tanımlamadan direkt metot gövdesi açıp tanımlayabiliyoruz.

C# 3.0 da ise bu örnek lambda ifadeleri, var deyimi ve kolkesiyon ilk atam değerleri kullanılarak aşağıdaki hale geliyor.

- C# 3.0 Mantığı
static void Main()
{
       var sayilar = new List<int>(){1,2,3,4,5,6}; //koleksiyon ilk atama , C# 3.0’a özgüdür.

       var ciftSayilar = sayilar.FindAll( val => val % 2 ==0);

       foreach (int i in ciftSayilar)
       {
              Console.WriteLine(i);
       }
}



Yukarıdaki kod bloğunda bulunan FindAll metodunun parametresine Lambda İfadesi denilmektedir. Lambda ifadesi aslında IL de bir fonksiyona denk düşmektedir.

=> imgesi artık bir operatör olarak ele alınmaktadır. val => val % 2 == 0 ifadesi ile geriye bool dönen ve int türünden bir parametre alan bir fonksiyon tanımlamış oluyoruz. Üretilen değerin ve parametrenin tipi açıkca belirtilmemiş olsa bile derleyici ifadeyi ayıklayarak buna karar vermektedir. İstersek ifadeyi şu şekilde de tanımlayabiliriz : (int val) => val % 2 == 0 yada (int val) => { return val % 2 == 0;} Birden fazla parametre alan lambda ifadeleri söz konusu ise parametreler virgül ile aşağıdaki gibi tanımlanabilir.

(x, y) => x+y yada (int x,int y) => {return x+y;}

Lambda deyimleri genel olarak bu şekilde tanımlansa da lambda deyimleri ile ilgili bilinmesi gereken başka konularda var. Özellikle metot aşırı yükleme ve otomatik tür dönüşümleri ile ilgili bazı kısıtlamalar mevcut. Butün bunları inceleyebileceğini C# 3.0 Specification dökümanını aşağıdaki bağlantıya tıklayarak indirebilirsiniz.

C# 3.0 Specification dökümanını indirmek için tıklayınız.

C# 2.0 ve C# 3.0 Yeniliklerini Kullanan Faydalı Bir Örnek

Dilde yapılan diğer değişiklik olan sorgu ifadelerine(query expressions) geçmeden önce öğrendiğimiz yenilikleri kullanarak faydalı bir örnek yapalım. Zaten bu örnek sorgu ifadelerini anlamımıza bir hayli yardımcı olacaktır.

Örnek uygulamada List<T> koleksiyonuna bir genişletme metodu ekledim ve boylece bu metot yardımıyla herhangi bir koleksiyon üzerinden SQL deki where koşuluna benzer sorgulamalar yapma şansına sahip oldum. Biraz karışık ve ilk bakışta gerçekten anlaşılması zor bir örnek oldu. İtiraf etmek gerekirse bende bunu yaparken epey zorlandım. Ama yapıya alışınca ne kadar güçlü bir yapı olduğunu sizde farkedeceksiniz. Size tavsiyem yukarıdaki ilk 3 örneği iyice hazmettikten sonra bu örneği incelemeniz. Örneğin çalışması için herhangi bir özel isim alanını eklemenize gerek yok. C# 3.0’a eklenen dil özelliklerini kullanarak yaptım. Birazdan Query Expression yapısını gördüğümüzde aslında bu ifadelerin arka planda neye dönüşmüş olduğunu daha net anlamış olacaksınız.

using System;
using System.Collections.Generic;
using System.Text;

namespace MyQueryExpression
{
     class Program
     {
          static void Main(string[] args)
          {
               List<Personel> personeller = new List<Personel>{new Personel{Ad = "Ali",No = 3 }};

               personeller.Add(new Personel{Ad = "Ali",No = 27 });
               personeller.Add(new Personel{Ad = "Sefer",No = 5 });
               personeller.Add(new Personel{Ad = "Ali",No = 6 });
               personeller.Add(new Personel{Ad = "Oguz",No = 8 });

               //SelectWhere List<T> sınıfına bizim eklediğimiz genişletme metodudur.
               var aliOlanlar = personeller.SelectWhere(p => p.Ad == "Ali");
               var nosuBestenBuyukOlanlar = personeller.SelectWhere(p => p.No > 5 );

               foreach (Personel ali in aliOlanlar)
               {
                    Console.WriteLine( "Ad : " + ali.Ad + " No:" + ali.No.ToString());
               }
          }
     }

     public delegate bool ConditionTester<T>(T val);

     public static class MyExtensions
     {
          public static IEnumerable<T> SelectWhere<T>(this List<T> liste, ConditionTester<T> secici)
          {
               foreach (T val in liste)
               {
                    if (secici(val))
                    {
                         yield return val;
                    }
               }
          }
     }

     public class Personel
     {
          public string Ad;
          public int No;
     }
}


Gördüğünüz gibi sadece bir temsilci(delegate) ve genişletme metodu(extension metot) ekleyerek herhangi türden bir koleksiyon üzerinden esnek bir sorgulama işlemi yapabiliyorum. Birazdan inceleyeceğimiz sorgu ifadelerinde bunu bir adım daha öteye taşıyacağız. Ancak bilmeniz gerekirki sorgu ifadelerinin altında yatan mantık yukarıdaki örnekteki gibidir.

Yukarıdaki örnekte kafanıza takılan ve anlamakta güçlük çektiğiniz bir nokta olursa bana e-mail aracılığıyla ulaşırsanız elimden geldiğince yardımcı olmaya çalışırım.

6 - Sorgu İfadeleri (Query Expressions)

C# 3.0 diline eklenmiş en önemli özellik sorgu ifadeleridir. Yukarıdaki örnekte verdiğimiz SQL stili sorgulamayı direkt olarak dile entegre edilmiş haline sorgu ifadeleri denilmektedir. Belirli kriterlere göre varolan bir koleksiyon kaynağından alt bir küme seçmek için metotları kullanmak yerine dile eklenen bu yapılar sayesinde herhangi bir SQL dilinde yaptığımız sorgulara benzer sorgular hazırlayabilmekteyiz. Örneğin bir Personel koleksiyonunda numarası 5 den büyük olanları isim sırasına göre sıralayıp isimleri büyük harflerle gösterilmiş şekilde bir alt küme elde etmek için aşağıdaki gibi bir deyim yazılabilmektedir.

using System;
using System.Collections.Generic;
using System.Text;

namespace LINQTest
{
     class Program
     {
          static void Main(string[] args)
          {
               List<Personel> personeller = new List<Personel>();
               personeller.Add(new Personel{Ad="Sefer",No=3});
               personeller.Add(new Personel{Ad="Ali",No=6});
               personeller.Add(new Personel{Ad="Mehmet",No=2});
               personeller.Add(new Personel{Ad="Burak",No=16});
               personeller.Add(new Personel{Ad="Oguz",No=10});

               //var sonuclar = .. şeklinde de diyebilirdik.
               IEnumerable<string> sonuclar = from val in personeller
                                                                          where val.No > 5
                                                                          orderby val.Ad
                                                                          select val.Ad.ToUpper();


               foreach (string ad in sonuclar)
               {
                    Console.WriteLine( ad );
               }
          }
     }

     public class Personel
     {
          public string Ad;
          public int No;
     }
}



Örneği derleyip çalıştırdığınızda ekrana,

ALI
BURAK
OGUZ

yazdığını göreceksiniz. Gördüğünüz üzere herhangi bir tipten bir koleksiyon üzerinde esnek ve hızlı sorgulamalar yapabiliyoruz. Yukarıdaki kodlarda kalın olarak işaretlenmiş where,orderby,from ve select gibi deyimlerin aslında arka planda birer genişletme metoduna (extension method) denk geldiğini bilmemiz gerekir. Yani yukarıdaki kod derleyici içindeki parser tarafından aslında önce aşağıdaki gibi çevrilmekte ve ardından derleme işlemi gerçekleşmekte.

Not 1: Dikkat ettiyseniz select, from deyimleri SQL diline göre ters çevrilmiş durumda.
Not 2: Yukarıdaki deyimler en temel LINQ yapısıdır. Daha karmaşık yapıları bir sonraki makalemde ele alacağım.

IEnumerable<string> sonuclar = from val in personeller
                                                     where val.No > 5
                                                     orderby val.Ad
                                                     select val.Ad.ToUpper();

IEnumerable<string> sonuclar = personeller.Where( val => val.No > 5).OrderBy(val => val.Ad).Select(val => val.Ad.ToUpper());



Gördüğünüz gibi herbir yapı aslında parametre olarak bir lambda ifadesi alan metottan başka birşey değil. Bu yapı dikkat ettiyseniz bizim yaptığımız örnekteki SelectWhere genişletme metoduna çok benzemektedir. Bunun gibi C# 3.0’a eklenmiş SelectMany, Groupby gibi bir çok genişletme metodu daha bulunmaktadır. LINQ genel mimari olarak lambda ifadeleri ve genişletme metotlarının üzerine kurulduğu için bunun gibi bir çok eklenti çok rahatlıkla geliştirilebilmektedir. C# 3.0 geliştiren ekip ise bu elentileri dile entegre ederek bizlere kullanım kolalığı sağlamaktadır.

Bu makalede C# 3.0’ın yeniliklerinden ve LINQ mimarisi hakkında bilgiler vermeye çalıştım. Dile eklenen özellikler genel olarak bu kadar olmasına rağmen henüz burada değinmeğim bir çok LINQ özelliği bulunmaktadır. Bir sonraki makalemde LINQ elemanları hakkında daha geniş bilgi verip LINQ altyapısının veritabanlarına uyarlanmış hali olan DLINQ ve XML verilere uyarlanmış hali olan XLINQ’ten bahsedeceğim.

LINQ, DLINQ ve XLINQ elemanlarını daha detayaylı ele alacağım ikinci makalemde görüşene dek esen kalın...

C# 3.0 ve genel olarak LINQ hakkında detaylı bilgilere aşağıdaki adresten erişebilirsiniz.

http://msdn.microsoft.com/vcsharp/future/default.aspx

Kaynakça

- The LINQ Project, Anders Hejlsberg
- C# 3.0 Specification
Makale:
C# 3.0 : Dil Yenilikleri ve LINQ (Language Integrated Query) .NET 3.0 ve .NET 3.5 Özel Bölümü Sefer Algan
  • Yazılan Yorumlar
  • Yorum Yaz
ARA
16
2011
Mükemmel Ötesi Bir Makale Olmus Emeğinize Bilgi Paylasmadaki Cesurlugunuza Saglık Hocam...
KAS
27
2010
Çok teşekkürler hocam, süper bir yazı olmuş...
MAR
5
2009
Hocam elinize sağlık şu zamanda linq öğrenmeye başladım ve temelde bu bilgilere ihtiyacım vardı, çok teşekkürler
ARA
28
2007
En son örneği çok beğendim elinize sağlık
ARA
23
2007
dsadasdsad
EKİ
18
2007
Çok başarılı bir makale olmuş. Konu gayet güzel açıklanmış. Elinize sağlık.
ŞUB
27
2007
test
Sayfalar : 1 
Yorum yazabilmek için üye girişi yapmalısınız. Üye girişi için tıklayın.
Üye değilseniz Üyel Ol linkine tıklayarak üyeliğinizi hemen başlatabilirisniz.
 
  • Bu Konuda Son 10
  • Eklenen Son 10
  • Bu Konuda Geçmiş 10
Bu Konuda Yazılmış Yazılmış 10 Makale Yükleniyor
Son Eklenen 10 Makale Yükleniyor
Bu Konuda Yazılmış Geçmiş Makaleler Yükleniyor