Caner Tosuner

Leave your code better than you found it

C# Extension Method Kullanımı

Kelime anlamı genişletilebilir metod olan Extension Method'lar C#3.0 ile hayatımıza girmiştir ve yaptığı iş itibatiyle kullanım açısından son derece faydalı metodlardır. Tek cümleyle özetlemek gerekirse class ve struct yapılarını modify etmeden ilgili struct yada class'için extension metodlar eklememizi sağlar.

 Extesion metod yazarken uymamız gereken bir kaç kural vardır. Bunlar;

  • Extension metodlar static bir class içerisinde static olarak tanımlanmalıdır. 
  • Extend edilecek class ilgili extension metoda metodun ilk parametresi olarak verilip önünde this keyword'ü ile tanımlanmalıdır
  • Extension metod da tanımlı parametrelerden sadece 1 tanesi this keyword'ü ile tanımlanır

Hemen bir örnek üzerinde inceleyelim. Case'imiz şu olsun; Bir tane extension metodumuz var ve bu metod integer bir değer alıp asal mı değil mi diye kontrol etsin.

public static class MyExtensions
   {
       public static bool IsPrime(this int integer)
       {
           //tembellik edip implementation'ı yazmakla uğraşmadım :)
           return true;
       }
   }

Yazdığımız metodu aşağıdaki görselde olduğu gibi kullanmak istediğimizde int tanımlı değişkenin adı"." nokta dediğimizde extensionMetod'u intellisense de görebileceğiz. 

class Program
{
    static void Main(string[] args)
	{
		int anyNumber = 123456;
		if(anyNumber.IsPrime())
		{
			//asal sayı
		}
		else
		{
			//asal sayı değil
		}
	}
}

Heralde en güzel yanı da bu olsa gerek metodu extension tanımladığımız için sanki o metod int struct'ına içerisinde tanımlı bir metodmuş gibi direkt olarak "." nokta deyip kullanabiliyoruz. 

Yukarıda ki örnekte int tipini baz alarak ilerledim ancak ihtiyaç dahilinde bütün tipler ve kendi tanımladığımız objeler içinde extension metodlar yazabiliriz.

Yine örnek olarak ; bir Person class'ımız ver ve içerisinde DateTime tipinde ismi BirthDate olan bir property olsun. Bir tane GetBirthDate adında extension metod tanımlayalım ve bu metod bize parametre olarak aldığı Person objesinde bulunan BirthDate alanını return ettirsin.

public class Person
{
	public string FullName {get;set;}
	public DateTime BirthDate {get;set;}
}

public static class MyExtensions
{
	public static DateTime GetBirthDate(this Person prs)
	{
			return prs.BirthDate;
	}
}

 

Şimdi bu metodu kullanan kısmı yazalım

using System;
					
class Program
{
    static void Main(string[] args)
	{
		Person prs=new Person();
		DateTime bDAte = prs.GetBirthDate();
	}
}

Görüldüğü gibi Extension metod kullanım alanımızı ihtiyaca göre genişletip metodlarımızı istediğimiz yerde "." nokta diyerek fıtı fıtı çağırıyoruz :)

.Net Assembly nedir ?

Assembly mi .Net Assembly mi ?

Genelde assembly nedir diye sorulduğunda belkide %80'imiz eski bir programlama dili olan assembly ile karıştırırız ancak aslında soruyu .Net Assembly nedir diye sorsak daha doğru bir soru olacaktır.

.Net Framework ailesindeki dillerden biriyle bir uygulama geliştirdiğimizde yazmış olduğumuz kodlar programlama dilinin derleyicisi kullanılarak bir .dll ya da .exe ye dönüştüğünde kodlar bir assembly içerisine koyulur. Nedir bunlar diye soracak olursak ;

.Net Assembly 4 bölümden oluşur

  1. IL
  2. Metadata
  3. Manifest
  4. Resources

 

 

1) IL

.Net ailesinde bulunan dillerden herhangi biri ile yazmış olduğumuz kodlar derlendikten sonra IL kodlarına dönüşür ve .Net Assembly'da ki IL katmanı bu kodları barındırır. Ancak bu kodlar makine kodu değildir, CLR tarafından makine koduna dönüştürülür. 

 

2) Metadata

Metadata içerisinde uygulamayı yazarken kullandığımız değişkenler, metodlar, external .dll' ler ve onların hangi metodlarının yada değişkenlerinin kullanıldığı bilgisi gibi tanımlamalar bulunur. Örneğin Main fonksiyonunda  Console.WriteLine("Caner Tosuner");  diye bir tanımlamamız olsun.

using System;

class MainApp
{
    public static void Main()
    {
        Console.WriteLine("Caner Tosuner");
    }
}

Metadata içerisinde Console sınıfının WriteLine metodunun kullanıldığı bilgisi yer alır. Yada bizim uygulamada kendi tanımladığımız class ların (Person class'ı gibi) bilgileri ve onların hangi property veya metodlarının kullanıldığı bilgisi de bulunur. Bu arada Visual Studio'da Metadata bilgisinden faydalanmayı ihmal etmemiş, intellisense de VS'da geliştirme sırasında bize öneriler sunarken aslında metadata bilgisinden faydalanmaktadır. 

 

3) Manifest 

Manifest assembly metadalarını diğer bir değişle kimlik bilgilerini tutar. Nedir bu bilgiler diye soracak olursak; assembly versiyon numarası, ürün adı, assembly adı, şirket bilgileri, yasal uyarılar, başka assembly'lerle referans yoluyla olan ilişkileri vs gibi bilgiler tutular. 

 

4) Resource

Uygulamada kullanılan kaynak dosyaların bulunduğu yer. Nedir bu dosyalar ; resim dosyaları, gif'ler, html-xml yada resource files vs olabilir.

 

C# 6.0 ile Gelen Yenilikler

Microsoft C# 6.0 'ı daha önce release ettiği sürümlere istinaden çok büyük major feature'lar ile kullanıma sunmadı desek çokta yanlış olmaz herhalde. Ancak 6.0 ile major feature'ların dışında geliştirici için development yapmasını çok daha kolaylaştıracak diyebileceğimiz bir takım önemli değişiklikler sundu. Daha öncesinde aynı işlemleri yapabilmek için satırlarca kod yazdığımız işlemler artık birkaç satırda yapılabilecek duruma gelmiş. 

6.o ile gelen feature listesi aşağıda ki gibidir.

 

1) Auto-Property Initializer

Daha önceki C# sürümlerinde field'lar için kullanılabilir olan initializer artık auto-property'ler için de kullanılabilecek. 

Öncesinde

using System;

namespace CSharpSix
{
    class Program
    {
        static void Main(string[] args)
        {
            Customer cust = new Customer();
            Console.WriteLine(cust.customerID);
            Console.ReadLine();
        }
    }

    public class Customer
    {
        public Customer()
        {
            customerID = Guid.NewGuid();
        }
        public Guid customerID { get; set; }
    }
}

 C# 6.0 ile

using System;
using static System.Console;

namespace CSharpSix
{
    class Program
    {
        static void Main(string[] args)
        {
            Customer cust = new Customer();
            WriteLine(cust.customerID);
            ReadLine();
        }
    }

    public class Customer
    {
        public Guid customerID { get; set; } = Guid.NewGuid();
    }
}

  

2) Using Static

Daha önceleri projede ilgili class'ta herhangi bir yerde static sınıfları kullanmak istediğimizde sınıfın adıyla birlikte o sınıfın fonksiyonlarını çağıra bilmekteydik. 

Öncesinde

class Program
{
    static void Main()
    {
        Console.WriteLine(Math.Sqrt(5*2 + 4*3)); 
        Console.WriteLine(System.DayOfWeek.Friday - System.DayOfWeek.Monday); 
    }
}

Artık C# 6.0 ile birlikte bu statik sınıfları using ile tanımlayıp sonrasında o sınıfa ait metotları kullanabileceğiz. 

C# 6.0 ile

using static System.Console;
using static System.Math;
using static System.DayOfWeek;
class Program
{
    static void Main()
    {
        WriteLine(Sqrt(5*2 + 4*3)); 
        WriteLine(Friday - Monday); 
    }
}

 

3) Expression-bodied methods

Lambda expresiion C# 3.5 ile gelen en büyük değişiklikti ve lambda sayesinde uzuuunnn mu uzun delegate kodları yazmaktansa o satırlara karşılık gelen lambda tanımlamalarını yazabilmekteyiz. Eğer yazılan metod geriye tek satırlık bir işlem yapıp değeri return ediyorsa bu işlem lambda expression ile de yazılabilecektir. 

Öncesinde

namespace CSharpSix
{
    class Program
    {
        private static double MultiplyNumbers(double num1, double num2) 
        { 
           return num1 * num2;
        }

        static void Main(string[] args)
        {
            double num1 = 3;
            double num2 = 6;

            Console.WriteLine(MultiplyNumbers(num1, num2));
            Console.ReadLine();
        }
    }
}

C# 6.0 ile

using static System.Console;

namespace CSharpSix
{
    class Program
    {
        private static double MultiplyNumbers(double num1, double num2) => num1 * num2;

        static void Main(string[] args)
        {
            double num1 = 3;
            double num2 = 6;

            WriteLine(MultiplyNumbers(num1, num2));
            ReadLine();
        }
    }
}

 

4) Null Conditional Operator

Developerlar için kaçınılmazdır ki bir objenin veya tanımlanmış olan bir değerin "null" mı değil mi diye sürekli kontrol etme durumunda kalmışızdır ve bu kontrol için genelde min 2 satır kod yazmak zorundayızdır. if(obj!=null) ... şeklinde. C# 6.0 ile birlikte null check yapma işlemleri biraz daha kolay hale getirilmiş.

Öncesinde

using System;

namespace CSharpSix
{
    class Program
    {
        static void Main(string[] args)
        {
            Person person = new Person();
            if (person.Name == String.Empty)
            {
                person = null;
            }

            Console.WriteLine(person != null ? person.Name : "Field is null.");
            Console.ReadLine();
        }
    }

    public class Person
    {
        public string Name { get; set; }
    }
}

C# 6.0 ile

using System;
using static System.Console;

namespace CSharpSix
{
    class Program
    {
        static void Main(string[] args)
        {
            Person person = new Person();
            if (person.Name == String.Empty)
            {
                person = null;
            }

            WriteLine(person?.Name ?? "Field is null.");

            ReadLine();
        }
    }

    public class Person
    {
        public string Name { get; set; } = "";
    }
}

 

5) String Interpolation

String bir ifadeyi formatlayıp farklı şekilde bir string birleştirme işlemi vs yaparak göstermek itediğimizde string.format("{0} {1}","Caner", "Tosuner"); vs şeklinde tanımlıyorduk. 6.0 il birlikte bu formatları ve ifadeleri yapmak biraz daha kısa hale getirilmiş diyebiliriz. 

Öncesinde

using System;

namespace CSharpSix
{
    class Program
    {
        static void Main(string[] args)
        {
            string firstName = "Caner";
            string lastName = "Tosuner";

            Console.WriteLine("Name : " + firstName + " " + lastName);
            Console.WriteLine("Name : {0} {1}", firstName, lastName);

            Console.ReadLine();
        }
    }
}

C# 6.0 ile

using static System.Console;

namespace CSharpSix
{
    class Program
    {
        static void Main(string[] args)
        {
            string firstName = "Caner";
            string lastName = "Tosuner";

            WriteLine($"{firstName} {lastName} is my name!");

            ReadLine();
        }
    }
}

Bu yazım şekliyle birlikte string format yazımının karmaşasından da kurtulmuş oluyoruz.

 

6) Exception Filters

try içerisinde bir exception alınıp carch'e düştüğünde exceptiona neden olan şeyle ilgili bir spesification yapmak istediğimizde genelde catch bloğu içerisinde if(ex.Message.Equals("bişey bişey")) şeklidne yazarız. 6.0 ile catch bloğu yanına bu if condition'ları yazabilir hale geliyoruz ve her condition'nın kendi catch'i oluyor.

Öncesinde 

using System;

namespace CSharpSix
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                throw new Exception(404);
            }
            catch (Exception ex)
            {
                if (ex.Message.Equals("500"))
                    Console.Write("Bad Request");
                else if (ex.Message.Equals("401"))
                    Console.Write("Unauthorized");
                else if (ex.Message.Equals("402"))
                    Console.Write("Payment Required");
                else if (ex.Message.Equals("403"))
                    Console.Write("Forbidden");
                else if (ex.Message.Equals("404"))
                    Console.Write("Not Found");
            }
           Console.ReadLine();
        }
    }
}

C# 6.0 ile

using System;
using static System.Console;

namespace CSharpSix
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
               throw new Exception(404);
            }
            catch (Exception ex) if (ex.Message.Equals("400"))
            {
                Write("Bad Request");
            }
            catch (Exception ex) if (ex.Message.Equals("401"))
            {
                Write("Unauthorized");
            }
            catch (Exception ex) if  (ex.Message.Equals("402"))
            {
                Write("Payment Required");
            }
            catch (Exception ex) if (ex.Message.Equals("403"))
            {
                Write("Forbidden");
            }
            catch (Exception ex) if (ex.Message.Equals("404"))
            {
                Write("Not Found");
            }
            ReadLine();
        }
    }
}

 

7) Await in a Catch and Finally Block

C# 6. ile birlikte artık Catch ve Finally blockları arasında await keyword'ünü kullanıp asynchronous çalışan kodlar yazabiliyoruz. Daha önce bunu yapabilmemiz mümkün değildi ve ihtiyaç halinde (logging etc.) çeşitli kontroller yapıp catch bloğundan çıktıktan sonra async yapmak istediğimiz işlemi yapardık.

Öncesinde 

using System;
using System.Net.Http;
using System.Threading.Tasks;

namespace CSharpSix
{
    class Program
    {
        static void Main(string[] args)
        {
            bool isException=false;
            try
            {
                throw new notimplementedexception();
            }
            catch (Exception exception)
            {
                isException = true;
            }
             if(isException)
                 var result = await LogManager.Log("Hata oluştu !" + exception.Message);
            Console.ReadLine();
        }
    }
}

C# 6.0 ile

using System;
using System.Net.Http;
using System.Threading.Tasks;
using static System.Console;

namespace CSharpSix
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                throw new notimplementedexception();
            }
            catch (Exception exception)
            {
                var result = await LogManager.Log("Catch => Hata oluştu !" + exception.Message);
            }
            finally
            {
                var result = await LogManager.Log("Finally => Hata oluştu !" + exception.Message);
            }            
           ReadLine();
        }
    }
}

 

8) Index initializers

Önceden bir List'e veya Dictionary'ye belirli bir index'ine item atamak istediğimizde önce initialize eder sonra nokta operatörüyle değerleri atardır. 6.0 ile birlikte initialize sırasında bu bu atam işlemlerini yapabilmekteyiz.

Öncesinde 

using System;

namespace CSharpSix
{
    class Program
    {
        static void Main(string[] args)
        {
           var dic = new Dictionary<int, string>
                        {
                            { 1, "one" },
                            { 4, "four" },
                            { 10, "ten" }
                        };
        }
    }
}

C# 6.0 ile

using System;

namespace CSharpSix
{
    class Program
    {
        static void Main(string[] args)
        {
           var dic = new Dictionary<int, string>
                          {
                             [1] = "one",
                             [4] = "four",
                             [10] = "ten"
                          };
        }
    }
}

Yukarıda 2 syntax'a baktığımızda ne fark var ki ikisi de aynı diyebiliriz ancak şöyle bir ayrım var. 6.0'dan önceki yazımda .Add() metodu kullanılarak initialize işlemi yapılıyor. Yeni syntax'da ise direkt olarak index assignments kullanılmakta ve bu da performans olarak daha verimli bir hale gelmekte. 

 

9) nameof Operatörü

Tanımlamış olduğumuz değişkenin veya objenin string olarak adına ulaşmak istediğimizde 6.0 ile birlikte gelen nameof operatörünü kullanabiliriz.

Öncesinde 

using System;

namespace CSharpSix
{
    class Program
    {
        static void Main(string[] args)
        {
            DoSomething("Selam");
            Console.ReadLine();
        }

        public static void DoSomething(string name)
        {
            if (name == null) throw new Exception("Name is null");
        }
    }
}

C# 6.0 ile

using System;
using static System.Console;

namespace CSharpSix
{
    class Program
    {
        static void Main(string[] args)
        {
            DoSomething("Selam");
            ReadLine();
        }

        public static void DoSomething(string newName)
        {
            if (newName == null) throw new Exception(nameof(newName) + " is null");
        }
    }
}

C# Ref ve Out Kullanımı

Object-Oriented programramming ile birlikte günümüz PC'lerinin de geçmişe göre bir hayli performanslı olması biz developer'ları git gide programlama dili & RAM ilişkisinden uzaklaştırıyor. Çok iyi hatırlıyorum üniversite 1. sınıfta C++ dersi almıştım ve dersi anlatan hoca ilk derste yanılmıyorsam şöyle bir cümle kurmuştu "Muhtemelen birçoğunuz ilk ve son defa bu derste Programlama ve RAM ilişkisini bu kadar yakından öğrenme şansınız olacak..". Tabi hoca bunu söylerken ne yazık ki bizde öyle çokta anlıyormuş gibi dinlememiştik. C# programlama dilinde kullanılan veri tiplerini 2 başlıkta tanımlayabiliriz. Değer tipleri ve Referans tipleri.

Kısaca tanımlamak gerekirse, değer tipler; ram de kaplayacağı alanı belli olan int,double,byte vs gibi struct olan tiplerdir ve stack'de bulunurlar. Referans tipler; string,object, kendi yazdığımız custom objeler bunlar ram'de kaplayacakları alan belli olmadığından heap'de tutulurlar. 

Gelelim konumuzun başlığında bulunan "ref" ve "out" parametrelerimize. C# da kullanıma sunulan ref ve out isminde iki tane parametre tanımlama çeşidi bulunmakta. Bu kullanımlarla birlikte ref ve out parametreleriyle yazmış olduğumuz metodlara değişkenleri göndermeden önceki değerleri ile metoddan çıktıktan sonraki değerleri kullanıma göre farklılıklar göstermektedir. Aslında ref veya out ile tanımlandığında RAM'de ne oluyor tanımlanmadığında ne oluyor, aralarında ne gibi farklar var bunları incelicez.

 

Geliştirme yaparken tanımlamış olduğumuz parametre alan metodları kullanmak istediğimizde ilgili metoda parametre geçme işlemi 2 yolla yapılır "pass by value" ve "pass by reference". Kısaca tanımlamak  gerekirse ;

  • Pass by value fonksiyona parametre gönderirken o parametrenin bir kopyasının oluşturulup gönderilmesi ve metod içerisinde yapılan değişikliklerden metod içerisinde ki yeni değerin etkilenmesi,
  • Pass by reference fonksiyona parametre gönderirken o parametrenin ram'de adresinin gönderilip metod içerisindeki yapılan değişiklerden orjinal değerin etkilenmesi.

 

Ref - Out Nedir den önce aşağıdaki örneği bir inceleyelim; C# da geriye herhangi bir değer dönmeyen bir metod yazalım ve içerisine int tipinde 3 değişken alsın sonrasında bu değerlerden birini metod içerisinde değiştirsin ve değişkenin metoddan önceki ve sonraki değerlerine bir bakalım 

public class RefOutExample
{
    static void Main()
    {
        int originalValue = 43;
 
        Console.WriteLine("ChangeMethod'dan önce: " + originalValue);//Output 43
 
        ChangeMethod(1,3,originalValue);
 
        Console.WriteLine("ChangeMethod'dan sonra: " + originalValue); //Output 43
    }
    static void ChangeMethod(int x, int y, int i)
    {
        i = i+x+y;//47
    }
}

 

Yukarıda ki örnekte ChangeMethod'isimli metoda parametreyi geçereken değişkenin orjinal halini değilde bir örneğini geçtiğimizden metod içerisinde ki değişiklik orjinal değeri etkilemedi.

 

C# Ref Kullanımı

Value Type'lar metodlara birebir kopyası oluşturularak geçirilirler ve metod içerisinde o değişkenle ilgili yapılan değişikliklerden orjinal değer etkilenmez. Ancak bazen değer tiplerini de referansları ile metodlara parametre olarak vermek isteyebiliriz. Referans yolu ile metoda parametre olarak geçtiğimiz değişken üzerinde yapılacak bütün değişiklikler orjinal değeri etkileyecektir çünkü artık o metod içerisinde değişkenin bir kopyası değilde RAM'de ki adresi bulunmaktadır. Örnek kullanımı aşağıdaki gibidir.

using System;
					
public class RefOutExample
{
   public static void Main()
    {
        int originalValue = 43;

        Console.WriteLine("ChangeMethod'dan önce: " + originalValue);//Output 43

        ChangeMethod(1,3,ref originalValue);

        Console.WriteLine("ChangeMethod'dan sonra: " + originalValue); //Output 47
    }

    static void ChangeMethod(int x,int y, ref int i)
    {
        i = i+x+y;//47
    }
}
 

Yukarıda görüldüğü gibi ChangeMethod'una bu sefer parametreyi ref keyword'ü kullanarak geçtik ve bu metoda o değişkenin örneğini değilde RAM'de bulunan adresini geçtiğinden "i" parametresi metodu çağırırken kullandığımız "originalValue" değerine refer ettiğinden yapılan bir değişiklik "originalValue" parametresinin kendisine yapılmıştır.

 

Ref'in Özellikleri

  • Metodu tanımlarken referans yolu ile iletilmek istenen değişkenin önüne "ref" yazılmalıdır. 
  • originalValue değişkeni metoda parametre olarak geçilmeden önce bir başlangıç değeri almak zorundadır,
  • "i" değişkeni metod içerisinde herhangi bir değişiklik yapmadan da kullanılabilir.

   

C# Out Kullanımı

Out aslında ref ile hemen hemen aynı amaca hizmet ediyor diyebiliriz. Ancak ref ile aralarında temel 2 farklılık var bunları aşağıda ki Ref-Out Farklılıkları başlığında yazıyor olacağım

 

Out'un Özellikleri

  • Metodu tanımlarken geçilmek istenen değişkenin önüne "out" yazılmalıdır. 
  • originalValue değişkeni metoda parametre olarak geçilmeden önce bir başlangıç değeri almak zorunda değildir.
  • "i" değişkeni metod içerisinde herhangi bir değişiklik yapmadan kullanılamaz.

 

Yukarıda Ref için yazdığımız metodun aynısını Out içinde yazalım

using System;
					
public class RefOutExample
{
   public static void Main()
    {
        int originalValue;

        ChangeMethod(1,3,ref originalValue);

        Console.WriteLine("ChangeMethod'dan sonra: " + originalValue); //Output 47
    }

    static void ChangeMethod(int x,int y, out int i)
    {
        i = i+x+y;//47
    }
}

 

Ref-Out Farklılıkları

Ref Out
Metodu tanımlarken geçilmek istenen değişkenin önüne "ref" yazılmalıdır. Metodu tanımlarken geçilmek istenen değişkenin önüne "out" yazılmalıdır.
originalValue değişkeni metoda parametre olarak geçilmeden önce bir başlangıç değeri almak zorundadır. originalValue değişkeni metoda parametre olarak geçilmeden önce bir başlangıç değeri almak zorunda değildir.
"i" değişkeni metod içerisinde herhangi bir değişiklik yapmadan da kullanılabilir. "i" değişkeni metod içerisinde herhangi bir değişiklik yapmadan kullanılamaz.

   

Aynı metodda hem "ref" hem "out" kullanımı

Gelin birde hem ref hem out tanımlı parametreleri olan bir metod kullanalım

using System;
					
public class RefOutExample
{
   public static void Main()
    {
        int refValue=5;//başlangıç değeri atanması zorunludur.
        int outValue;//başlangıç değeri atanması zorunlu değildir.

        ChangeMethod(out outValue, ref refValue);

        Console.WriteLine("ChangeMethod'dan sonra refValue : " + refValue); //Output 7
        Console.WriteLine("ChangeMethod'dan sonra outValue: " + outValue); //Output 8
    }

    static void ChangeMethod(out int i,ref int j)
    {
          i = 8; // i argümanına bir değer atamak zorunludur
          j = j + 2; // j için böyle bir zorunluluk yoktur
    }
}

 

Daha çok C - C++ dillerinde etkin bir şekilde kullanılan pass by reference C# dilinde de developer'ların kullanımına sunulmuş. Birden fazla parametre dönmesini istediğimiz metodlar da veya orjinal veri üzerinde method içerisinde işlem yapmak istediğimizde ref ve out keywordlerinden kolayca faydalanabiliriz.

C# Destructor Nedir ?

Destructor kısaca constructor'ın tam tersidir.Constructor için bir nesnenin instance'ı alınırken Ram'de ki Heap bölümünde yer ayırmadan önce çağrılan metod diyebiliriz. Destructor tam bu nesne ram'den silinmeden önce çağrılan metod dur. 

Peki neden buna gerek var dersek; garbage collector sağ olsun bizim için ram'de işleri bitmiş nesneleri ram'den siliyor ve bazen tam bu silinme anını bilmek isteriz. Aslında C# tarafında çok fazla ihtiyaç duyulan bir şey değil ancak C-C++ gibi Ram yönetimini developer'a bırakan programlama dillerinde Destructor'a çok fazla ihtiyaç duyuluyordu. C# ram yönetimini tamamiyle developer'a bırakmadığından gerek kalmadıkça bu metodu kullanmıyoruz.

Destructor Özellikleri

  • Her class'ın sadece bir tane Destructor'ı olabilir,
  • Destructor tanımlanırken class ismini başına "~" işareti koyulur,
  • Struct'lar için tanımlanamaz, sadece class'lar için tanımlanırlar,
  • Dışarıdan çağrılamaz, otomatik olarak invoke olur,
  • Destructor parametre alamaz.
  • Kalıtım yapılamazlar ve overload edilemezler.

 

Örnek kullanım olarak;

	class Person
	{
		~Person()  // destructor
		{
			// cleanup statements...
		}
	}

Kullanımı yukarıda olduğu gibidir. Yazım olarak Constructor tanımlar gibi yazıyoruz ancak isminin başına "~" işaretini koyuyoruz.

sealed class nedir

Kalıtım nesneye dayalı programlamada ki en büyük etkendir. Projede tanımladığımız bir class başka bir class veya interface'den ihtiyaca göre inheret olabilir ve böylelikle bir nevi oop'nin faydalarından yararlanmış oluruz. Ancak bazen yazmış olduğumuz bir class'ın başka class'lara kalıtım vermesini istemeyebiliriz. Neden böyle bir şeye ihtiyaç duyalım ki dersek genellikle security konularından dolayı böyle bir durum söz konusu olabilir. C# tarafında bu ihtiyacımızı karşılayacak olan sealed  keyword'ü bulunmaktadır. Eğer bir class sealed tanımlanırsa bu class alt class'lara kalıtım veremez.

Örnek olarak ; sealed tanımlı A class'ımız olsun ve 2 tanede sealed olmayan B,C adında class'larımız olsun

// Sealed class
sealed class A
{

} 
public class B
{

} 

//Sorunsuz çalışır
public class C : B
{

} 


//Hata verir !!!  cannot derive from sealed type 'A'
public class C : A
{

} 

C class'ı B class'ından kalıtım alabilirken A class'ından kalıtım alamayacaktır. Çünkü A class'ı sealed'dır ve başka hiçbir class'a kalıtım veremez. 

.Net Framework içerisinde bir çok sealed class bulunmaktadır. Bunlardan en tanınmış olanı String class'ı dır. Bu nedenledir ki herhangi bir class String class'ından kalıtım almaya çalıştığında "cannot derive from sealed type 'string'" hatasını verir. 

Smart Home Project

Summary

Smart Home project provides users to control the electronic devices via it’s desktop application and mobile application. User can create scenarios which are “Arrive” and “Leave” scenarios and they can create feature events about sensors or electronic devices which are time-based and the system perform these events according to the different device types. All the actions process on the system are logged in the database and reports to the user.

 

 

Desktop Application

There is a laptop which is connected to the arduino and it receives and sends data from cloud system to arduino board or arduino board to cloud system. Users can access the in time data that comes from arduino board and it is displayed on a page which works on desktop application. They can create “Arrive” and “Leave” scenarios or they can create feature events using that application.

 

 

Cloud

 In the cloud side all data and necessary files are stored on azure cloud services. All the tables in the database have been developed by using MS-SQL, and using Entity Framework technology insertion, deletion and update operations performed. There is a virtual machine runs on azure and it communicates with mobile application and desktop application the process the commands.

 

 

 

 

Mobile Application

 There is an application which works on Windows Phone operating system. Users who has Windows Phone device can install the application and login. After processing some security functions they can easily display the device status and values of the sensors that are in smart home system.

 

Use Case Diagram

 

ADO.Net Entity Framework Hız Testi

Bu makalede local'de bulunan northwind database'ine bağlanarak Customers tablosunda bulunan müşterileri hem ADO.Net hem de Entity Framework kullanarak alıp array içerisine atacağız ve iki işlem arasındaki hız farkını ölçmeye çalışacağız.

 

Entity Framwork'ün developerlara ne derece kolaylık sağladığını biliyorsunuzdur.Normal şartlarda ADO.Net kullanarak ortalama 20 satır kodla yaptığınız işlemleri Entity Framework ile %60 daha az kod yazarak yapabiliyoruz. Düşünüldüğü zaman inanılmaz bir durum ve zamandan kazanç sağlamak için muhteşem bir mimari. Bende aynen böyle düşünüyordum taki aradaki hız farkının en kötü şartlarda bile 3 kattan daha fazla olduğunu öğrenen kadar. Gelin aşağıda örneğimizi inceleyerek devam edelim. 

 

Öncelikle Northwind database'inde bulunan Customers tablosunun colonlarını aşağıda olduğu gibi classlaştırıyoruz

public classCustomer
    {
        public int CustomerID { get; set; }
        public string CompanyName { get; set; }
        public string ContactName { get; set; }
        public string ContactTitle { get; set; }
        public string Address { get; set; }
        public string City { get; set; }
        public string Country { get; set; }
        public string Phone { get; set; }
    }

 

Sonrasında ADO.Net ile database'de kayıtlı bulunan müşterilerin bilgilerini alıp Customer objesinden bir List array'in içerisine dolduruyoruz,

public List<Customer> GetCustomers_By_ADO()
{
List<Customer> AllCustomers = newList<Customer>();
 
SqlConnection conn = newSqlConnection("Server=CT;database=Northwind;trusted_connection=True");
SqlCommand cmd = newSqlCommand("select * from Customers", conn);
conn.Open();
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
AllCustomers.Add(newCustomer()
{
CustomerID = dr.GetString(0),
CompanyName = dr.GetString(1),
ContactName = dr.GetString(2),
ContactTitle = dr.GetString(3),
Address = dr.GetString(4),
City = dr.GetString(5),
Country = dr.GetString(8),
Phone = dr.GetString(9),
});
}
return AllCustomers;
 }

Şimdi ise aynı işlemi Entity Framework kullanarak yapıyoruz,

NorthwindEntities db = newNorthwindEntities();
public List<Customers> GetCustomersBy_EF()
{
List<Customers> AllCustomers = newList<Customers>();
AllCustomers = db.Customers.ToList();
return AllCustomers;
 }

Bakıldığı zaman ADO.Net ile yaklaşık 25 satırda yaptığımız işlemi Entity Framework ile 7 satırda hallediyoruz. Şimdi gelelim Hız testimize. Bir adet WebForm ekliyoruz ve içerisine aşağıdaki kodları yazarak testimizi yapıyoruz.

 

İlk olarak ADO.Net hızını test ediyoruz,

Stopwatch sw2 = newStopwatch();
sw2.Start();
Customer c1 = newCustomer();
c1.GetCustomers_By_ADO();
sw2.Stop();
string result2 = sw2.ElapsedMilliseconds.ToString();
Response.Write(result2 + " ms.");

 

 Şimdi Entity Framework kullanarak testimizi yapalım,

Stopwatch sw1 = newStopwatch();
sw1.Start();
Customer c = newCustomer();
c.GetCustomersBy_EF();
sw1.Stop();
string result = sw1.ElapsedMilliseconds.ToString();
Response.Write(result);

 

Sonuçlar Nasıl Mı ?

 

Ado.Net ile yapılan işlem;

Entity Framework ile yapılan işlem;

 Görüldüğü üzre aradaki fark neredeyse 7 kattan daha fazla.Bunun nedenine gelecek olursak, ADO.Net ile yapılan her bir sorguda istenilen türdeki obje 1 defa generate edilirken Entity Framework ile yapılan her bir sorgu için entity'niz sürekli generate edilir ve bu projeniz için çok yüksek oranda bir performans kaybına neden olur. Bu fark küçük çaplı projelerde belki göz ardı edilebilir ancak eğer ki proje gayet kapsamlı ve büyük bir projeyse inanılmaz derecede bir hız farkı ortaya çıkarmaktadır.

 

Son söz olarak ; ADO Candır !!

Web Service'de Güvenlik | Soap Header

Bu makalede Web Service Nasıl Yazılır ? makalesinde bahsettiğim üzre Web Service'de Soap Header Kimlik Denetimi yani Username Password ile service'i kullanabilme konusundan bahsediyor olacağım.

 

Web Service'in tanımına değinecek olursa M2M iletişimin önünü açmak ve back-end sistemlerde var olan çeşitli database yada enterprise yapıların diğer platformlarla iletişimini güvenli bir şekilde sağlamak için geliştirilmiş yapılardır, Kısacası farklı platformların haberleşmelerini sağlamak için kullanılan teknolojilere verilen isimdir. Web Service Nasıl Yazılır ? makalesinde local'de bulunan Northwind database'ine bağlanarak Employees tablosundaki çalışanların bilgilerini getiren bir .asmx servis geliştirmiştik, hatırlicak olursanız projeyi kendi bilgisayarımızda çalıştırdığımızda aşağıdaki resimlerde olduğu gibi çok rahat bir şekilde metod isimlerine tıklayıp Çağır butonuna bastığımızda servis çalışıp istenilen verileri bize getiriyordu.

 

 Yukarıda da gördüğümüz gibi her şey sorunsuz çalışıyor ancak anormal olan durum service URL'ini bulan herhangi biri gidip aynı service'i kullanarak database'de kayıtlı bulunan verilere erişebilir ve bu durum hiç bir şirket yada service sahibi tarafında istenilen bir durum değildir.Güvenlik durumunda web service'ler için kullanılabilecek çeşitli yöntemler vardır bunlardan ençok tercih edileni kuşkusuz Soap Header'dır. Soap Header kullanarak service tarafında belirleyeceğimiz UserName ve Password ile Client'ın service'e bu UserName ve Password kullanarak girişine izin vereceğiz.

1.Adım | Proje ve Class'ın Oluşturulması

  • Visual Studio'da "Northwind" isminde bir adet ASP.Net Empty Web Application oluşturuyoruz. Sonrasında proje içerisine aşağıda olduğu gibi 1 adet User adında "SoapHeader"'dan kalıtım alan class oluşturuyoruz ve içerisine service'e login esnasında kullanacağımız attributeleri yazıyoruz.

   

 public class User : SoapHeader
    {
        public string Username;
        public string Password;
    }

 

2.Adım | Service Sayfasının ve WebMethod'un Oluşturulması

  • Bu adımda projemize sağ tıklayıp 1 adet "MyService" adında Web Service sayfası ekliyoruz ve içerisine aşağıda olduğu gibi kullanacağımız WebMethod'larını yazıyoruz

 

public User User;  //Oluşturmuş olduğumuz User class'ından 1 adet User tanımlıyoruz
 
[WebMethod]        
[SoapHeader("User")]  //Güvenlik burda devreye giriyor, WebMethod'a SoapHeader içerisinde bulunan User nesnesi ile giriş yapıldığını belirtiyoruz
public string KullanıcıGirisi()
{ 
   //Client tarafında UserName ve Password bilgileri doğru girildiğinde ve girilmediğinde yapılması gerekenleri belirtiyoruz
   if (User.Username == "caner" && User.Password == "tosuner")
      return "Kullanıcı Girişi Başarılı";
   else
      return "Kullanıcı Girişi Başarısız";
 }

 

 

Bütün bu işlemler sonrasında Projemizin Solution bölmümü sağ tarafta olduğu gibidir

 

 

 3.Adım | Client Tarafından Service'e İstekte Bulunulması

  • Solution'a sağ tıklayıp 1 adet "Client" adında ConsoleApplication oluşturuyoruz ve sonrasında solution'da bulunan iki projenin haberleşebilmesi için Client ta bulunan References'a sağ tıklayıp "Add Service Reference" diyoruz ve açılan penceren Discover'a tıklayıp solution'da bulunan Northwind projesini görmesini sağlayıp Service bir isim Verdikten sonra OK butonuna basıyoruz. Client'ta bulunan Program.cs class'ını açıp Main metodunun içerisini aşağıda olduğu gibi dolduruyoruz.

 

Northwind.ServiceReference1 sc = new Northwind.ServiceReference1 ();  //Referans olarak eklediğimiz service'in ismi
Northwind.User user= new Northwind.User ();   //Servis içerisinde bulunan SoapHeader'dan kalıtım almış nesnemizi seçiyoruz.
 
user.Username = "caner";   //Servis tarafında oluşturduğumuz Username ve Password bilgilerini user nesnesinin attributlerine yazıyoruz
user.Password = "tosuner";
 
string result= sc.KullanıcıGirisi(user);  //KullnıcıGirisi WebMethod'una user nesnesini veriyoruz ve return edilen sonucu ekranda yazıdırıyoruz.
Console.WriteLine(result);
 
Console.ReadKey();

 

Projeyi çalıştırdığımızda UserName ve Password bilgilerini doğru yazdığımızdan aşağıda olduğu gibi Kullanıcı Girişi Başarılı mesajını ekranda görmüş olacağız.

Web Service Nasıl Yazılır ?

Web Service günümüz teknolojilerinin olmazsa olmazları arasında yer almaktadır. Bunun en büyük nedeni M2M iletişimin önünü açmak ve back-end sistemde var olan çeşitli database yada enterprise yapıların diğer platformlarla iletişimini güvenli bir şekilde sağlamaktır.  

.Net tarafında çeşitli Web Service yazma yolları vardır bunlardan bir tanesi asmx dediğimiz [WebMethod]’ lar kullanılarak yazılan servislerdir. Aşağıda ki örnekte Database’den veri çekilerek nasıl bir asmx servis yazılıp çekilen veri internet ortamında yayınlanır ona değiniyor olacağız.

1.Adım | Projenin Oluşturulması

  • Öncelikle aşağıdaki resimde de olduğu gibi ismi "WebService" olan bir adet Asp.Net Empty Web Application oluşturuyoruz

2.Adım | Projeye Web Service Sayfası Eklenmesi

  • Projeyi oluşturduğumuzda içerisinde default olarak Properties, References ve Web.config sayfalar geliyor. WebMethod yazabilmek için Proje ismine sağ tıklayıp aşağıda ki resimde de olduğu gibi bir adet ismi "WebMethods" olan WebService sayfası ekliyoruz.

  3.Adım | WebMethod 'un Anlaşılması

  • Service sayfasını ekledikten sonra kodlarını açtığımızda içerisinde default olarak gelen bir adet HelloWorld() metodu bulunmaktadır
[WebMethod] // [WebMethod] tag'i altında yazılı olan Metodun bir "Web Method" olduğunu belirten yapıdır. Aslında kabacası bizim internette yayınlayacağımız ve Client tarafında kullanılacak metod olduğunu belirtiyor.
publicstring HelloWorld()  //Herbir .asmx service sayfasında Default olarak gelen parametre almadan geriye string dönen HelloWorld() bulunmaktadır.Browser'da servici çalıştırdığınızda aşağıda resimde olduğu gibi metodları görüyor olacaksınız
DipNot - [WebMethod] tanımlaması yapılan metodlar Browser'da görünmeyecektir, Sadece [WebMethod] etiketine sahip metodlar burda görünür ve Client tarafından direkt olarak kullanılır
{
return"Hello World";
}

4.Adım | Web Service Nasıl Bir İşlem Yapıyor Olacak ?

  • Geliştireceğimiz Web Service local'de bulunan Northwind Database'ine bağlanarak Employees tablosunda bulunan Çalışanların Ad(FirstName), Soyad(LastName) ve İş Tanımı(Title) bilgilerini yayınlıyor olacak.Bunun için öncelikle pc'nizde Northwind database'i bulunuyor olması gerekli. Olmayan arkadaşlar bu Link' teki script'i indirip MS-SQL Management Studio kullanarak kurulum yapabilirler.

5.Adım | Database'den Employees Bilgilerini Çeken Metodun Yazılması

  • Database ile bağlantı kurmanın çeşitli yolları vardır.İster Entity Framework kullanırsınız istersenizde klasik Ado.Net yazarsınız.Ben Ado.Net'in Entity Framework ve yandaşlarına kıyasla 7 kat gibi bir hız farkıyla çalışmasında dolayı Ado.Net kullanıyor olacağım Smile. İlk olarak "Employees" tablosundan "FirstName" ,"LastName" ve "Title" bilgilerini almamız için bu attributelere sahip "Employees" class'ını aşağıdaki gibi oluşturuyoruz
public class Employees
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Title { get; set; }
 }
  • Şimdi ise Ado.Net kullanarak çekeceğimiz bu Employees'leri List<Employees> array'i oluşturup içerisine atıp sonrasında Web Service' imiz ile yayınlıyor olacağız. Geriye List<Employees> dönen CallEmployees() adında bir metod tanımlayalım ve kodlarımızı aşağıda olduğu içerisine yazalım.
[WebMethod]
public List<Employees> CallEmployees()
{
//Employees'leri içerisine doldurup return ettireceğimiz List<> array
List<Employees> AllEmployees = new List<Employees>();
 
//Local'de bulunan Northwind database'ine bağlanmamızı sağlayan connectionstring'i
SqlConnection conn = new SqlConnection("server=.;database=Northwind;trusted_connection=True");
 
//Hangi bilgileri çekeceğimizi belirttiğimiz sql sorgumuz
SqlCommand cmd = new SqlCommand("select FirstName,LastName,Title from Employees", conn);
conn.Open(); //Sql bağlantısını açıyoruz
SqlDataReader dr = cmd.ExecuteReader();  //DataReader kullanarak verileri alıyoruz
while (dr.Read())
{
//Çektiğimiz verileri Employee nesnesi'nin attribütlerine atayıp sonrasında AllEmployees array'inin içerisine atıyoruz
AllEmployees.Add(new Employees()
{
FirstName = dr.GetString(0),
LastName = dr.GetString(1),
Title = dr.GetString(2)
});
}
//Son olarakda doldurduğumuz array'i return ediyoruz
return AllEmployees;
}
  • Projeyi Run ettiğimizde Browser'da aşağıda olduğu gibi HelloWorld() metoduyla birlikte bizim sonradan tanımladığımız CallEmployees() metodunu görüyor olacağız. 1. resimde bulunan metodumuza tıkladığımızda 2. resimde gördüğümüz sayfa açılıyor olacak ve Çağır butonuna tıkladığımızda son resimde gördüğümüz gibi Database'den gelen veriler XML formatında görüntüleniyor olacak.

 -

 6.Adım | Web Service'in Internet'te Yayınlanması

  • Geliştirmiş olduğunuz bu gibi Web Servic'i yayınlamak için Solution'dan proje üzerine sağ tıklayıp Publish deyip sonrasında generate edilmiş dosyaları web sitenizin bulunduğu ftp' ye atmanız yeterli olacaktır.
  • Yazılmış olan bu web service'i diğer projelerde kullanmak için ise service'in bulunduğu sayfayı projelerinize Reference olarak ekleyip sonrasında içerisinde bulunan metodları kullanabilirsiniz.Biz projede sadece select işlemi yapan bir WebMethod yazdık ama ihtiyaca göre çok daha farklı inserti, update, delete gibi işlemler yapan WebMethod'larda yazılabilir.

 7.Adım | Web Service' de Güvenlik

  • Makalenin başında da bahsettiğimiz gibi Web Service'ler şirketler için büyük önem taşırlar nedeni ise veri'nin sadece istenilen kişiler tarafından kullanılması. Biz yukarıda geliştirmiş olduğumuz projede güvenlik olarak hiç birşey yapmadık yani siz bu projeyi internette publish ettikten sonra çeşitli yazılımlar kullanılarak data-sniffing ile servis'in bulunduğu URL bulunup yazmış olduğunuz metodlar diğer kişiler tarafındanda kullanılabilir.İşte bu gibi durumlarda güvenlik çok büyük öneme sahip oluyor.Konu uzun olduğu için Web Service'de Güvenlik Nasıl Sağlanır ? bir sonraki makalemizde görüyor olacağız. Umarım buraya kadar yazdıklarımız yararlı olmuştur, herhangi bir sorunuz olduğunda e-mail ile ulaşabilirsiniz,

 

Projeyi burdan indirebilirsiniz..