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=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
}
}
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.