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.

 

Sharepoint Rest Get User By

Get All Users List 

http://your-site-name/_vti_bin/ListData.svc/UserInformationList

 

Get A User By Account or Any Other Property

http://your-site-name/_vti_bin/ListData.svc/UserInformationList?$filter=Account eq ‘contoso\administrator’&$select=Id,Name

 

Get Users by Content Type

http://your-site-name/_vti_bin/ListData.svc/UserInformationList? $filter=ContentType eq ‘Person’

Sharepoint Callout Position Problem

I don't know why but I had this problem when I display Search Results. The position of the callout popup did not work what ıt was expected. 

 

To solve this problem modified "ms-wpContentDivSpace" style in core15.js has position:relative, which breaks the hover placement. Overriding that as position:inherit in custom CSS works around and solved the problem.

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");
        }
    }
}

XAML Binding Mode OneWay, TwoWay

Binding, Binding..

Eski den WPF ile uğraşanların oldukça haşır neşir olduğu ve Windows8-WindowsPhone sonrası tamamen hayatımıza girmiş olan XAML ve onun getirdikleri. XAML ile UI geliştirenler Binding'i yakından tanırlar.

Nedir bu Binding diye soracak olursak;

"Databinding(Veri Bağlama) kısaca bir veri kaynağını (Array, Dictionary,Object), bir UI kontrolüne bağlamaya yarayan bir tekniktir."

 

 

Üstteki görselde de görüldüğü üzre Source olarak kullandığımız bir objemiz var ve bu objede ki property'ler de set edilen değerleri XAML tarafta bulunan UI kontrollerine Binding yaparak aktarıyoruz.

 

 Peki ya UI Control için Binding nasıl yapılır dersek aşağıda bulunan görsel nasıl kullanıldığını oldukça iyi özetler gibi.

Yukarıda görüldüğü üzre Source "Article" adında bir class ve içerisinde string tipinde bir "Title" property'si olsun. Bu property'yi TextBox'ın Text'ine Binding olarak set ediyoruz. Böylece şu olmuş oluyor Article objesindeki Title propery'si nin değeri değiştiğinde UI thread'i tetikleyerek Bind olduğu control'ün property'sini de güncelleyecektir.

 

Binding Modları

Binding Modları, binding işlemi sırasında source'ta bulunan verinin değiştiğinde UI'da Bind edildiği yrerin değişip değişmeyeceği veya UI da Bind edilen property'nin içeriği değiştiğinde source da bulunan verinin değişip değişmeyeceğine karar veren özellik diyebiliriz. Bu özellik Binding sınıfının “Mode” property'si ile belirlenir. Bunlar; OneWay, TwoWay, OneTime, OneWayToSource ve Default’ dur.

 

OneWay

Source yani Bind edilen property update edildiği anda UI taraftaki yani target control'de Bind edilen yer de değişir.

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

Örneğin bir INotifyPropertyChanged interface'ini implemente etmiş bir Person class'ımız olsun ve bu class'ta bulunan Name alanı UI tarafta bir Textbox'ın Text alanına Bind edilmiş olsun. (INotifyPropertyChanged implementasyonun şu yazıda bulabilirsiniz.)

<TextBox Text="{Binding Name}, Mode=OneWay}"/>

Person objesinde ki Name alanı Codebehind'dan değiştirildiğinde bu değişimden TextBox'ı da haberdar edip Text property'sini de güncelleyecektir.

 

TwoWay

Source yani Bind edilen property update edildiği anda UI da Bind edilen yer de değişir. Aynı şekilde UI'da bulunan control'ün property'si kullanıcı tarafından değiştirildiğinde yani TextBox'a birisi birşeyler yazdığında codeBehind'da Bind edildiği alanıda günceller.

<TextBox Text="{Binding Name}, Mode=TwoWay}"/>

Yukarıda verdiğimiz örnekten devam edelim. Kullanıcı ilgili TextBox'a kendisi birşeyler girip Text'i değiştiğinde bu değişiklikten source'u yani Person objesinde ki Name alanını güncelleyecektir.

 

OneTime

UI tarafında ki control source'dan yani Person objesindeki Name property'sinden sadece 1 defa değerini alır ve ondan sonra ki Name property'sinin güncellenmesi UI tarafı etkilenmez. Ördeğin uygulama açıldıktan sonra Name = "Caner" dedik ve TextBox'ın Text'i de "Caner" oldu ancak bundan sonraki bütün Name="bla bla.." değişikliklerinden TextBox'ın Text'i etkilenmeyecektir.

 

OneWayToSource

OneWay BindingMode'unun tam tersi gibi çalışır. TextBox'ın Text'ine kullanıcı tarafından birşeyler girildiğinde Person objesindeki Name alanını da update eder.Örnek olarak; kullanıcı uygulamada TextBox'ın Text'ine bir şeyler girdiği anda Person class'ında ki Name alanıda otomatik update olur ancak CodeBehind'dan Name alanı değiştirildiğinde bu değişiklik TextBox'ın Text'ine yansımaz.

 

Sharepoint Hide Ribbon

To hide the ribbon nav bar from your html you can get use of these two ways;

First way add the below css class to your css file

#s4-ribbonrow {
    display: none;
}

 

Second way use javascript to hide it

<script type="text/javascript"> document.getElementById("s4-ribbonrow").style.display = "none"; </script>

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.