C# events (olaylar) kavramı

18 Ara

Bir önceki yazımızda delegates (delegeler veya temsilciler) kavramından bahsetmiştik. Delegelerin amaçlarından birinin de event(olay) yakalyıcı metodları temsil eden tipler olduğunu vurgulamıştık.

Olaylar .Net platformunun ileri konularından biri olup ilk anda anlaşılması biraz karmasık gelebilir. Olayları anlamanın yolu da delegeleri anlamaktan geçer. Delegeler konusu anlaşılmışsa olayların (events) anlaşılması da çok basit bir hale gelecektir.

C# ortamında bir event tanımlamak şu şeklidedir:

<erişim belirleyici> event <delege tipi> <event adı>;

Public event QueryEventHandler QueryExecuted;

Public: erişim belirleyicisi. Public veya private olabilir.

QueryEventHandler: delege tipi.

QueryExecuted: event adı.

Event kullanımı .Net platformunda genellikle form tabanlı windows uygulamalarında, silverlight uygulamalarında, network uygulamalarında çok yaygındır. Örneğin bir windows forms uygulamasında bir butona tıklandığında Buton sınıfının Click adındaki event’ı için bir metod oluşturulur ve bu metod içerisine tıklama işlemi sonrası yürütülecek kodları yazabiliriz.

Biz bu yazımızda örnek olarak bir önceki c# delegeler yazımızdaki örneğin aynısını event kullanarak yapacağız. Bu sayede event ve delegate arasındaki bağıntıyı kurmak daha da kolaylaşacak.

Öncelikle bir önceki uygulamamızda ki büyük resme bakarak başlayabiliriz.

Client tarafında oluturduğumuz bir metodu Queryoperation tipinin ExecuteQuery metoduna parametre olarak göndermiştik. ExecuteQuery metodu da bizim gönderdiğimiz metod formunda bir delegeyi parametre aldığı için uygulamamız hiç sorunsuz çalışmıştı.

Bu sefer Queroperation sınıfımıza QueryExecuted adında bir event tanımlayarak bu event’a client tarafındaki bir metodu abone edeceğiz. Sorgu işlemi gerçekleştiğinde abone ettiğimiz metod çalışacaktır.

QueryOperation sınıfının artık QueryExecuted adında bir event’ı var. Bu event, void geri dönüş tipinde tipinde olan ve QueryEventArgs tipinde parametreler alan metodları yakalamakla sorumludur.

Client tarafında olayın nasıl gerçekleşeceğine bakacak olursak.

QueryOperation nesnesinin QueryExecuted event’ına client tarafında oluşturduğumuz, delegemize uygun olan onExecuted metodumuzu abone ediyoruz.

Bir metodun bir event’a abone edilmesi (+=) şeklinde yapılırken aboneliğin sona erdirilmesi ise (-=) şeklinde yapılır.

operation.QueryExecuted-=onExecuted;

şeklinde aboneliği sonlandırabiliriz. Bu sonlandırmadan sonra onExecuted metodu tetiklenmez.

Eğer event’a bir metod abone etmezsek QueryOperation sınıfının ExecuteQuery metodu içerisindeki if(QueryExecuted!=null) şartı false olarak değerlendirilir ve bizim client tarafındaki metodumuz çalıştırılmaz.

Bu yazımızda:

  • C# dilinde event kavramını
  • Event tanımlamasının nasıl yapıldığını
  • Event ve delegate arasındaki ilşkiyi
  • Event’a metod aboneliğini ve aboneliğin sonlandırılmasından
bahsettik.

Tekrar görüşmek dileğiyle…

C# delegate (Delege veya Temsilci) Kavramı

16 Ara

Bu yazımızda C# programlama dilini öğreneneler için bazen işkence haline dönüşen ve bir .Net kavramı olan delegeler üzerinde duracağız. Delegeler, adından da anlaşılacağı üzere temsilcidirler. Temsil ettikleri kavram ise metodlardır.

Delegelerin hangi tür değerleri dönrüren ve ne tür parametre alan metodları temsil ettiklerini tanımlanırken belirleriz.

Bir delegenin tanımlanış şekli aşağıdaki gibidir.

Örnek delege:

<erişim belirleyici> delegate <geri dönüş tipi> <delege adı>(<parametreler>)

 public delegate int Hesaplayici(int a,int b);

Örnek delegemizin tanımlanış biçimindeki ifadelerin ne anlama geldiklerini ise sırayla şu şeklide ifade edebiliriz.

Public: delegenin erişim belirleyicisi. Public veya private olabilir.

int: metodun geri dönüş tipi. Yani geri dönüş tipi int olan metodları temsil ediyor.

Hesaplayici: delegenin adı.

int a, int b: delegemiz, int tipinde iki adet parametre alan metodları temsil ediyor.

Yukarıda tanımlanan Hesaplayici adlı delege, int tipinde değerler döndüren ve int tipinde iki adet parametre alan metodları temsil etmektedir.

Burada aslında kafaları kurcalayan soru işareti, delegelerin bize sağladığı kolaylığın ne olacağı noktasında yatmaktadır.

Delegelerin temel olarak bize iki noktada büyük faydası vardır. Bunlar:

  • Event kullandığımız programlamada olayların yakalanacağı metodları belirlemek.
  • Çalışma zamanında (runtime) hangi tür metodların kullanılabileceğini belirlemek.

Delegelerin daha iyi anlaşılması açısında bu yazımızdaki örnek uygulamızda delegelerin çalışma zamanında (runtime), belirlediğimiz bir metodun temsil edilmesini canlandırmaya çalışacağız.

Senaryo şu şeklide olacaktır: Sql sorgularını icra etmekle sorumlu bir sınıfın metoduna, sorgu sonrasında bizim gönderdiğimiz bir görevi(metodu) yerine getirmesini sağlamaya .alışacağız. Yani bir metoda parametre olarak bir metod göndereceğiz. Sorgu sonrasında bizim gönderdiğimiz metod çalışacak.

Öncelikle query sonuçlarını yakalayan bir delege olan QueryResultHandler adında bir delege tanımlayacağız.

public delegate void QueryResultHandler(QueryEventArgs args);

Query sonuçlarını bildiren QueryEventArgs adında bir tipimiz mevcut. Bu tipte parametre alan ve void yani geriye birşey döndürmeyen metodların temsilcisini tanımlamış olduk.

public class QueryEventArgs
{
     public bool Executed { get; set; }
}

QueryEventArgs tipi aslında sadece sorgu sonucunda işlemin gerçekleşip gerçekleşmediğini argüman olarak bize veren bir tiptir.

Sql sorgu işlemlerini gerçekleştirecek olan tipimizi de QueryOperation adında bir tip olarak belirleyelim.


public class QueryOperation
{
     public void ExecuteQuery(string queryText, QueryResultHandler executed)
     {
        // execute query
        // ...
        // ..
        // .

        QueryEventArgs result =new QueryEventArgs();
        result.Executed = true;

        executed(result);
     }
}

Sınıfımız temsili bir sınıf olduğu için yani sql sorgusu gerçekleştirmiş gibi bir varsayım aptığımız bir sınıf olduğu için içeriğinde sadece ExecuteQuery adında bir metod tanımladık. Bu metod sorgu işlemini gerçekleştirip QueryEventArgs tipinde bir sonuç oluşturmakta ve parametre olarak gönderilen metodu çalışıtrmaktadır.

Şimdi client tarafında nasıl bir operasyon gerçekleştireceğimize gelelim.

static void Main(string[] args)
{
    QueryOperation operation = new QueryOperation();
    operation.ExecuteQuery("select * form Table", onExecuted);
}

public static void onExecuted(QueryEventArgs args)
{
    Console.WriteLine("query executed!");
}

Yaptığımız işlem sadece QueryOperation tipinde oluşturduğumuz bir nesneye sql sorgu parametresini ve sorgu sonrasında bizim client tarafında tanımladığımız bir metodun parametre olarak göndermektir. Bizim burada tanımladığımız onExecuted metodu tam da delegemizin (QueryResultHandler) formuna uyan bir yapıdadır.

Burada farkına varmamız gerekn bir nokta da delegelerin metod pointer(işaretçi) olduğudur. QueryOperation tipinin ExecuteQuery metodu bir temsilciyi parametre alırken, çalıştırılan bir metoddur. Yani temsilciler metodları işaret ederler.

Programı çalıştırdığımızda aşağıdaki gibi bir sonuç karşımıza çıkacaktır.

Bu örnekte:

  • delege tanımlamanın nasıl yapıldığını
  • çalışma zamanında (runtime) belirlenen bir metodun temsilcisinin çalıştırılmasını
  • delegelerinin birer metod pointer(işaretçi) olduğunu

anlamaya çalıştık.

Bir sonraki yazıda görüşmek dileğiyle…

GIT Nedir? ve Windows için GIT

28 Kas

GIT bir versiyon kontrol sistemidir. Yazılımcılar için geliştirme sürecinde önemli bir yeri olan versiyonlama mekanizmasını otomatikleştirebilen bir sistemdir. GIT, kökeni Linux tabanlı bir topluluk olsa da Windows tarafındaki gönüllüler sayesinde Windows dünyasına da kazandırılmıştır. Windows için GIT geliştirmek amacıyla MSys/MinGW projeleri baz alınmıştır.

Git for Windows(MinGW) projesi temel düzeyde Git kullanıcılarına hitap ederken, msysGit projesi geliştiriciler, testçiler, bakım ve dağıtım ekibi tarafına hitap etmektedir.

Hem MinGW hem de msysGit projelerinin depolama yeri Web tabanlı GitHub platformudur.

Ben kendi projelerimi versiyonlamak için msysGit uygulamasını kullanıyorum. msysGit programına buradan ulaşabilirsiniz. Programı indirip kurmak gayet basit olduğu için kurulum anlatımı yapmadım.

Programın kullanım arayüzü olarak komut ve GUI destekli olmak üzere iki seçeneği bulunmaktadır.

Git grafiksel arayüzü (Git GUI) şu şekildedir:

Git GUI

Git komut arayüz görüntüsü (Git Bash) şu şeklidedir:

Git Bash

Git Bash için bazı komutlar şu şeklidedir:

clear: Komut ekrarnını temizler.

mkdir: Bulunduğunuz dizin içerisine yeni bir dizin oluşturur.

ls: Bulunduğunuz dizindeki dosya ve dizinleri listeler.

cd: Dizin değiştirir.

git –version: Sistemde kurulu olan Git versiyonunu verir.

git init: Bulunduğu dizine “.git” adında yeni bir git deposu(repository) oluşturur.

git add: Çalıştığınız dizindeki dosyalarda oluşan değişiklikleri indekse ekler.

git status: Çalıştığınız dizindeki dosyaların indeksteki durumunu gösterir.

git commit: İndekse yazılmış tüm değişiklikleri alır ve bu değişiklikleri işaret eden yeni bir icra(commit) nesnesi oluşturur ve bu icra nesnesine şube ayarlar.

git remote: uzak depoların takma adlarını listeler.

git remote add: projenize yeni bir uzak depo ekler.

git push: Değiştirilmiş tüm yerel nesneleri uzaktaki depoda bulunan şubelere atar.

Yukarıdaki komutlar ile bir depo(repository) oluşturup uzaktaki bir depoya gönderme işlemi yapılabilmektedir. Bu komutlardan başka birçok komut vardır ancak şimdilik yeterli olacak komutlar elimizdekilerdir.

Örnek Uygulama

Geliştiriciler olarak projelerimizi versiyonlar halinde uzak bir depoda tutmak istediğimizde aklımıza ilk gelecek olan GitHub platformudur. Git de zaten bu platforma veri gönderebilmektedir.

Bu örnek uygulamamızda bir Visual Studio projemizi msysGit yardımıyla GitHub üzerinde oluşturduğumuz bir depoya(repository) göndermeye çalışalım.

Git tarafında ön bilgiye sahip olduğumuza göre bir de GitHub tarafında neler yapmamız gerektiğine göz atalım. Öncelikle GitHub web sayfasında bir hesap oluşturmamız gerekmektedir. Hesap oluşturduktan sonra GitHub web sayfasında “Create New Repository” veya “New Repository” şeklinde oluşturulmuş link yardımıyla yeni depo oluşturma sayfasına yönlendiriliriz.

GitHub New Repository

Yukarıdaki resimde de görüldüğü üzere TestConsoleApplication adında bir repository oluşturuyoruz.

Dikkat: Github üzerindeki repository içerisine veri gönderebilmek için bir güvenlik seviyesi ayarı olan SSH Key oluşturup sitedeki Account Settings bölümüne kaydetmemiz gerekmektedir. Bu işlemi Github burada bizim için anlatmış. Bu ayarı yapmadığımızda gönderdiğimiz veriyi almayacaktır.

Bu güvenlik ayarını da başarılı bir şeklide yaptıktan sonra Visual Studio ortamında oluşturulmuş “TestConsoleApplication” adında bir c# projesini Github depomuza gönderelim.

Projemizi D sürücüsü üzerinde TestConsoleApplication adında bir dizinde tutacağız ve Git üzerinden bu dizinde işlem yapacağız.

Git Commands 1,2,3

KOMUT:1 D sürücümüzde projemizin bulundupu TestConsoleApplication dizinine girer.

KOMUT:2 Dizin içerisine .git adında bir yerel depo oluşturur. Oluşturulan bu dizin (.git) gizli olabilir. Göremezsseniz klasör seçeneklerinden  “gizli dosya ve klasörleri göster” seçeneğini seçip bakabilirsiniz.

KOMUT:3 Dosya değişikliklerini indekse ekler.

Git Commands 4

KOMUT:4 Yeni bir icra(commit) nesnesi oluşturur.

Git Commands 5,6

KOMUT:5 Projeye git@github.com:bayramucuncu/TestConsoleApplication.git depo yolunu ekler.

KOMUT:6 Değiştirilmiş tüm yerel nesneleri uzak depo adersine gönderir.

Gönderdiğimiz projeye web sitesi üzerinden göz atacak olursak şu şeklide bir manzara karşımıza çıkacaktır.

Github Repository

Bu test projesi Github üzerinde oluşturulmuş genel bir projedir. Herkese açık bir şekilde düzenlenmiştir.

Tekrar görüşmek dileğiyle.

FizzBuzz Kata NCrunch ve NUnit tools

11 Kas

FizzBuzz Kata

FizzBuzz uygulaması, girilen parametrelerden

3 ile bölünebilen sayılar için sonuç Fizz
5 ile bölünebilen sayılar için sonuç Buzz
3 ve 5 ile bölünebilen sayılar için sonuç FizzBuzz
Ne 3 ile ne de 5 ile bölünebilen sayılar için sayının kendisini veren bir birim test pratiğidir.

Unit Test Assert List

1- Result_ForDivisibleByThree_IsFizz
2- Result_ForDivisibleByFive_IsBuzz
3- Result_ForDivisibleByBothThreeAndFive_IsFizzBuzz
4- Result_ForDivisibleNeitherThreeNorFive

Yukarıda birim testlerin listesi çıkarılmıştır ve bu listeye göre testler icra edilmektedir.

NOT: Makinemdeki donanım (işlemci) yetersizliğinden dolayı hem görüntü kaydı hemde Visual Studio’nun çalışması sırasında NCrunch aracı eş zamanlı derlemelerde biraz yavaş kaldı. Çünkü video kaydı başlar başlamaz işlemci %100’lere dayandı.

Tekrar görüşmek dileğiyle.

Chain Constructors Refactoring C#

10 Eyl

Bir sınıfın birden fazla kurucu metodu (constructor) varsa, kod tekrarları da oluşacak demektir. Çünkü kurucu metodların fazla olması, parametrelerin fazla olmasını gerektirir. Dolayısıyla sınıfın üyelerinin tekrarlı bir şeklide atama işlemine tabi tutulması demektir. Bu kod tekrarlarının nasıl oluştuğunu şu örnekle inceleyebiliriz.


public class PersonManager
{
      private string firstName;
      private string lastName;
      private string socialSecurityNumber;
      private string age;

      public PersonManager(string firstName, string lastName)
      {
          this.firstName = firstName;
          this.lastName = lastName;
      }

      public PersonManager(string firstName, string lastName, string socialSecurityNumber)
      {
          this.firstName = firstName;
          this.lastName = lastName;
          this.socialSecurityNumber = socialSecurityNumber;
      }

      public PersonManager(string firstName, string lastName,string age, string socialSecurityNumber)
      {
          this.firstName = firstName;
          this.lastName = lastName;
          this.age = age;
          this.socialSecurityNumber = socialSecurityNumber;
      }

}

Private erişimli field’lar her kurucu metodda tekrarlı bir şekilde işleme sokulmuş. Bunun önüne şu şeklide geçmek mümkündür.


public PersonManager(string firstName, string lastName)
      :this(firstName,lastName,"Unknown", "Unknown")
{
}

public PersonManager(string firstName, string lastName, string socialSecurityNumber)
       : this(firstName, lastName, socialSecurityNumber, "Unknown")
{
}

public PersonManager(string firstName, string lastName, string socialSecurityNumber, string age)
{
       this.firstName = firstName;
       this.lastName = lastName;
       this.age = age;
       this.socialSecurityNumber = socialSecurityNumber;
}

Bu şekilde kodumuzu tekrarlı yapıdan arındırdık.

Tekrar görüşmek üzere.

Koşullu Mantığın Komutla Değiştirilmesi (Replace Conditional Dispatcher with Command)

5 Eyl

Programcıların öğrenme aşamasındaki alışkanlıklarından dolayı olsa gerek, koşullu mantığın kullanılması hat safhadadır. Olay Nesneye Dayalı programlamaya gelince, koşullu mantık bir takım değişikliklere uğrayabiliyor. Bu değişiklikler, aslında olması gereken değişikliklerdir. Bu değişikliklerle çoğu zaman karmaşık kod yapılarından kurtuluruz. Nasıl mı?


public class PersonManager
{
     public double GetHourlyRate(Person person)
     {
         if (person is Employee)
             return 2.0;
         if (person is Student)
             return 1.0;
         return 0.0;
     }
}

Yukarıda tanımlı GetHourlyRate metodu içerisinde person tipinin Employee veya Student olup olmadığı kontrol ediliyor. Bir süre sonra sisteme yeni bir tip eklendiğinde GetHourlyRate metodunda bir koşul daha eklenerek değişiklikler gerekecek. Bu iyi bir yöntem değil. Zaten Open Closed tasarım ilkesine de uymayan bir durum. Bu durumu değiştirelim.


public class PersonManager
{
       public double GetHourlyRate(Person person)
       {
           return person.GetRate();
       }
}

public class Person
{
     public virtual double GetRate()
     {
         return 0.0;
     }
}

public class Student:Person
{
     public override double GetRate()
     {
         return 1.0;
     }
}

public class Employee:Person
{
      public override double GetRate()
      {
         return 2.0;
      }
}

GetHourlyRate metodunda Person nesnesinin bir komutu olan GetRate kullanılıyor. Bu durumda sisteme istediğimiz kadar yeni tip ekleyebiliriz. Çünkü artık gelişime açık bir kod ortaya koyduk. Open Closed ilkesine uyduk.

Tekrar görüşmek dileğiyle.

c# indexer işlemleri

25 Tem

Indexer kavramı C# dilinde tipleri diziler gibi kullanılabilir hale getirmektedir. Tiplere ait nesneler tıpkı bir diziymiş gibi indexlere sahiptirler. Bunu örneklerle incelemeye çalışalım.

Tek boyutlu indexer


class Week
{

   string[] week = new string[]{"Pazartesi","Salı","Çarşamba","Perşembe","Cuma","Cumartesi","Pazar"};

   public string this[int i]
   {
       get { return i >= 0 && i < 7 ? this.week[i] : "Hatalı İndex"; }
   }

}

Haftanın günlerini temsil eden Week sınıfımızı oluşturduk. Week sınıfından oluşturulan nesneler üzerinden sınıf içindeki dizi elemanlarına Indexer sayesinde erişebilecek duruma geldik.


static void Main(string[] args)
{
    Week days = new Week();

    for (int i = -1; i < 8; i++)
    {
        Console.WriteLine(days[i]);
    }
}

Sonuç:

İki Boyutlu Indexer


class Coordinates
{
     int[,] coordinates = new int[,] { { 10, 12 }, { 58, 46 }, { 16, 76 } };

     public int this[int i, int j]
     {
         get { return coordinates[i, j]; }
     }
}

static void Main(string[] args)
{
     Coordinates coor = new Coordinates();

     for (int i = 0; i < 3; i++)
     {
         for (int j = 0; j < 2; j++)
         {
             Console.WriteLine(coor[i,j]);

         }
     }

}

Sonuç:

LINQ ile String Birleştirme

17 Tem

Bazen üyelerin emaillerini çekerek toplu mail göndermek durumunda kalabiliriz. Email listesini çekmek kolaydır. Fakat bir de bu emaillerin, aralarına noktalı virgül koyarak birleştirmesi işlemi vardır. Bu işlemi iki yolla yapabiliriz.

  • Email listesini SQL ortamında noktalı virgülle ayrılmış şekilde çekmek.
  • Email listesini dizi şeklinde SQL sorguyla alıp, birleştirme işlemini kod tarafında yapmak.

Biz ikinci yöntem üzerinde duracağız.

Elimizdeki email listesi şu şekilde olsun.


List<string> data = new List<string>
{
    "aaa@mail.com",
    "bbb@mail.com",
    "ccc@mail.com",
    "ddd@mail.com",
    "eee@mail.com"
};

Bu listeyi şimdi birkaç yöntemle birleştirmeyi deneyelim.

Birinci yol: LINQ Aggregate extension metodunun kullanımı.

var emails = data.Aggregate((s, e) => string.Concat(s, ";", e));

İkinci yol: String.Join extension metodunun kullanımı.

var emails = string.Join(";", data);

Her iki yönteminde çıktısı şu şeklide olacaktır:

"aaa@mail.com;bbb@mail.com;ccc@mail.com;ddd@mail.com;eee@mail.com"

LINQ / Lambda Expression

16 Tem

Bu yazımızda da LINQ sorgularının lambda ifadeleriyla nasıl yazıldığını inceleyelim. Uzun uzun yazılan LINQ sorgularını tek satırda yazmak mümkündür. Bu sayede hem temiz hemde rahat okunabilir bir kod ortayaçıkıyor.

Bir Employee sınıfı oluşturup, sorgulama yapmak için de bu tipe ait bir liste oluşturarak işe başlayabiliriz.


 public class Employee
 {
       public int id { get; set; }
       public string Name { get; set; }
       public double Salary { get; set; }

       public override string ToString()
       {
            return string.Format("Name: {0} Salary: {1}",Name, Salary);
       }
 }

Employee tipine ait liste de şu şekilde olsun.


 List<Employee> Employees = new List<Employee>
 {
      new Employee{ id=1102, Salary=1250, Name="Jim" },
      new Employee{ id=1802, Salary=2250, Name="Tim" },
      new Employee{ id=1650, Salary=3250, Name="Kim" },
      new Employee{ id=2102, Salary=1750, Name="Sim" },
      new Employee{ id=3182, Salary=1350, Name="Him" },
};

Sorgu: Maaşı 1900’den küçük olan çalışanları ada göre sıralayarak göster.

Linq Sorgusu

    var linqResult = from c in Employees
                     where c.Salary < 1900
                     orderby c.Name
                     select c;

Lambda Expression Sorgusu

var lambdaResult = Employees.Where(i => i.Salary < 1900).OrderBy(i => i.Name);

Sorguları çeşitlendirmek mümkündür. Sonuçta bu örnek göldeki bir damla gibidir.

Dictionary Key Value değerlerinin birleştirlmesi

11 Tem

Dictionary tarzı, Key – Value çiftlerinden oluşmuş tiplerin elemanlarını birleştirerek göstermek istediğimiz durumlar oluşatuğunda ne yapmalıyız? Ben genelde bu tarz işlemlerde LINQ nimetlerinden faydalanmayı uygun buluyorum. Aksi taktirde diziler ve indexleriyle uğraşmak zorunda kalıyorum.

Web uygulamalarında URL oluştururken parametre değerlerini girmek istediğimizde, parametre adları ve değerlerini Key Value çiftleri olarak değerlendirebiliriz.

Örneğin şu şeklide bir URL oluturmak istiyoruz. www.bayramucuncu.com/urunler?id=5&categoryId=9&color=blue

Bu URL’in Querystring bölümünü (id=5&categoryId=9&color=blue) kısmını bu şekilde oluşturmaya çalışalım.

Öncelikle query string oluşturacak metodu yazmalıyız. Bu metodumuz da anahtar ve değer ikililerini tutan bir Dictionry<string,string> parametresi almalı.


private string queryString(Dictionary<string, string> parameters)
 {
      if (parameters == null)
          throw new ArgumentNullException("Parametreler boş gönderilemez");

      var pairs = parameters.Select(i => string.Format("{0}{1}{2}", i.Key, "=", i.Value));
      var values = string.Join("&", pairs);

      return string.Join("&", pairs);
 }

Bu şekilde, amaçladığımız query string  oluşturma işlemini yapacak metodu hazırladık. Şimdi de sonuca bakalım.

queryString(new Dictionary<string, string> { { “id”, “5” }, { “categoryId”, “9” }, { “color”, “blue” } });

şeklinde gönderilen bir dictionary sonucunda karşımıza şu şeklide bir resim çıkıyor.

ve işlem başarılı!

Tekrar görüşmek dileğiyle.