C# - Parametre
Parametrelerin C# ve diğer programlama dillerinde çok önemli bir yeri vardır. Fonksiyonlar parametresiz çalışabilirler, ancak genellikle bir veya daha fazla parametreye sahip olurlar, bu da fonksiyonun görevini gerçekleştirmesine yardımcı olmaktadır.
Aşağıdaki kodu inceleyelim..
public int SayilariCarp(int sayi1, int sayi2)
{
return sayi1 * sayi2;
}
Parametreler fonksiyonları daha akıllı ve esnek hale getirmek için kullanılırlar. Yukarıdaki fonksiyona 2 parametre belirledik ve onu dinamik hale getirdik. Hangi değerleri fonksiyona girersek bize ona göre sonuç döndürecektir.
Kullanımı şu şekildedir..
SayilariCarp(10, 8);
Burada gördüğünüz temel parametrenin bir kullanımıdır, ancak parametrelerin davranışını değiştirmek için kullanabileceğimiz çeşitli seçenekler mevcut bulunmaktadır.
Opsiyonel Parametreler
Normalde yaratılan tüm parametrelere değer atamaya yönlendirilirsiniz. Çeşitli durumlarda bir fonksiyonun bazı parametrelerine isteğe bağlı değer atama söz konusu olabilir. C# 'da parametreyi tanımlarken varsayılan bir değer atanabilir ve eğer bu sonucu değiştirmeyecek türden olursa kullanmadığımızda kodun işleyişini ve sonucu değiştirmez.
Opsiyonel (isteğe bağlı) parametreli bir tanımı aşağıda görebilirsiniz..
public int Toplam (int sayi1, int sayi2, int sayi3, int sayi4 = 0)
{
return sayi1 + sayi2 + sayi3 + sayi4;
}
Son parametre (sayı4) artık isteğe bağlıdır, çünkü bunun için varsayılan bir değer sağlamış bulunmaktayız (0). Bunu fonksiyonu çağırırken, ister 3 parametreye, istersek de 4 üne değer atayabiliriz.
Aşağıda kullanımına ait örnek verilmiştir..
using System;
namespace ParemetreOrnek
{
class Program
{
static void Main(string[] args)
{
Matematik mat = new Matematik();
int toplam = mat.Toplam( 1, 2, 3 );
int toplam2 = mat.Toplam( 1, 2, 3, 100);
}
}
public class Matematik
{
public int Toplam(int sayi1, int sayi2, int sayi3, int sayi4 = 0)
{
return sayi1 + sayi2 + sayi3 + sayi4;
}
}
}
İstersek fonksiyonda birden fazla isteğe bağlı parametre tanımlayabilir, hatta hepsini bu şekilde yaratabiliriz. Unutulmaması gereken konu isteğe bağlı parametreler her zaman sonda tanımlanmaları gerektiğidir.
"Params" modifier (değiştiricisi)
Fonksiyonunuzda kaç adet parametre tanımlayacağınızı bilemiyorsanız, yani fonksiyonunuz parametresel açıdan dinamik ise, "params" ifadesini kullanabilirsiniz. Bazı durumlarda gerçekten çok faydası olmaktadır.
Aşağıdaki şekilde tanımlanmaktadırlar..
public void IsimleriBirlestir(params string[] isimler) { }
ve aşağıdaki şekilde kullanılmaktadırlar..
IsimleriBirlestir("Ali", "Veli", "Ahmet", "Mehmet" );
"Params" değiştiricisinin bilmeniz gereken bazı diğer özellikleri vardır. Bunlardan ilki istersek hiçbir parametre kullanmayabiliriz. Yani "IsimleriBirlestir();" şeklinde bir kullanıma izin verir. Bir diğer özellik fonksiyonun sadece 1 adet "Params" değiştiricisi tanımlamamıza izin vermesidir. Son olarak ta normal parametre ve "Params" değiştiricisini beraber tanımlayabiliriz. Ancak "Params" değiştiricisi sonda olmak zorundadır.
Aşağıdaki örnek gibi..
public void IsimleriBirlestir(string grupAdi, params string[] isimler) { }
Peki "Params" değiştiricisini bir fonksiyon içinde nasıl kullanırız. Cevap döngülerdir. Bu tarz yapıları döngüler ile nasıl kullandığımızı aşağıdaki örnekte inceleyelim..
using System;
namespace ParemetreOrnek
{
class Program
{
public static void Main(string[] args)
{
IsimleriBirlestir("Ali", "Veli", "Ahmet", "Mehmet");
Console.ReadKey();
}
public static void IsimleriBirlestir(params string[] isimler)
{
foreach (string isim in isimler)
Console.WriteLine(isim);
}
}
}
Değer ve Referans Parametre Tipi (Value / Reference)
C# ve diğer programlama dillerin de genel olarak iki parametre tipi vardır. Bunlar "değer" ve "referans" tipidir. C# 'daki varsayılan tip "değer" dir. Value (değer) tipi, nesneye referans yerine bir kopyasını gönderdiğiniz anlamına gelir. Bu, parametre olarak ilettiğiniz orijinal nesneyi etkilemeden, fonksiyonun içinden parametrede değişiklik yapabilmemize izin verir.
Aşağıdaki kodu inceleyelim..
using System;
namespace ParemetreOrnek
{
class Program
{
public static void Main(string[] args)
{
int sayi = 100;
Carpim2(sayi);
Console.WriteLine(sayi);
Console.ReadKey();
}
public static void Carpim2(int sayi)
{
sayi = (sayi * 2);
}
}
}
Burada "sayi" değişkenimize atadığımız "100" değerinden sonra, bunu "Carpim2" fonksiyonumuzda parametre olarak kullanıyoruz. Fonksiyonun içinde bu değer "200" olsa da sadece fonksiyonun içinde değişmekte. "sayi" değişkenini ekrana yazdırdığımızda değerinin "100" olarak değişmediğini görebilirsiniz. Bunun nedeni parametre value (değer) tipinde olduğu için orjinal nesnenin bir kopyası olarak işlem görmekte yani orjinal "sayi" değişkeninin değeri etkilenmemektedir.
"ref" değiştiricisi (modifier)
Ref değiştiricisi "referans" ın kısaltmasıdır ve parametrenin davranışını varsayılan olan "değere göre" den "referansa göre" olarak değiştirir. Artık bir referans ile orijinal değişkene değer atanır..
Aşağıdaki kodu inceleyelim..
using System;
namespace ParemetreOrnek
{
class Program
{
public static void Main(string[] args)
{
int sayi = 100;
Carpim2(ref sayi);
Console.WriteLine(sayi);
Console.ReadKey();
}
public static void Carpim2(ref int sayi)
{
sayi = (sayi * 2);
}
}
}
Değer tipi parametresi ile aynı örnek verilmiştir. Fakat 2 farkla, birincisi "Carpim2" fonksiyonunda "ref int sayi" şeklinde parametre tanımı yapılmış, ikincisinde ise kullanıldığı yer olan "Carpim2(ref sayi);" de ise gene "ref" anahtar sözcüğü kullanılmıştır. Bu örneği çalıştırdığınızda değişkenimiz olan "sayi", 100 olan değeri fonksiyona girip çıktığında 200 olmuş ve ekrana bu değer yazılmıştır. Çünkü "sayi" değişkeni fonksiyona paramatre olarak kendisini sokmuştur. Değer parametresi gibi kopyasını değil. Bu yüzden fonksiyondaki değişiklik (sayının 2 ile çarpımı) direk değişkene atanmıştır.
"out" değiştiricisi (modifier)
"out" değiştiricisi de "ref" değiştiricisi gibi parametrenin değere göre referansla geçirilmesini sağlar, Yani değer fonksiyona girip çıktığında değişir. Fakat "ref" ile arasındaki temel fark "out" değiştiricisinde bu parametreyi kullanma ve ona bir değer atama zorunluluğudur. Eğer bunu yapmazsanız derleme hata verecektir.
Aşağıdaki örnekte "out" parametresini nasıl kullanamayacağımız gösterilmektedir.
using System;
namespace ParemetreOrnek
{
class Program
{
public static void Main(string[] args)
{
int toplam;
Topla(10, 55, out toplam);
}
public static void Topla(int sayi1, int sayi2, out int toplam)
{
int deger_toplami = sayi1 + sayi2;
}
}
}
Örnek biraz anlamsız olsa da bu kodu yazdığınızda hata alırsınız. Çünkü derleyici sizden "toplam" değişkenine bir değer atanmasını (fonksiyon içinde) beklemektedir. Çünkü bu değişken (toplam) değeriyle sonunda fonksiyondan dışarı çıkarılması gerekmektedir. "out" yani dışarı çıkma denmesinin sebebi budur.
Doğru kullanım ise aşağıdaki gibi olmalıdır..
using System;
namespace ParemetreOrnek
{
class Program
{
public static void Main(string[] args)
{
int toplam;
Topla(10, 55, out toplam);
}
public static void Topla(int sayi1, int sayi2, out int toplam)
{
toplam = (sayi1 + sayi2);
}
}
}
"in" değiştiricisi (modifier)
- in parametre değiştiricisi C# 7.2 ve sonrası sürümlerde kullanılabilir..
"in" değiştiricisi de "out" ve "ref" gibi, referans tipinde bir parametre türü için kullanılır. "out" değiştiricisinin aksine fonksiyonun içine girdiğinde o parametrede bir değişiklik yapılmasına izin vermez. O parametreyi fonksiyon içinde "read-only" (salt-okunur) hale dönüştürür. "Eğer onu fonksiyon içinde değiştiremiyorsak neden böyle bir yapıya ihtiyacımız var ki ?" diye düşünebilirsiniz.
Bu yapının kullanılma nedeni, bir fonksiyonu birçok kez çağırma durumumuzda ve içine büyük değerlere sahip bir array (dizi), List veya bunlara benzer değişkenleri parametre olarak atadığımızda her seferinde onun kopyasını oluşturmamak (değer tiplerinde olduğu gibi) ve içerde defalarca atama yapmadan okumak içindir. Bu yüzden "in" değiştiricisi ile kullanılan parametreler demin söylediğmiz senaryolarda ciddi kaynak tasarrufu ve performans artışı sağlar. "ref" veya "out" değiştiricilerine göre çok az kullanılır fakat ihtiyaç duyulduğunda çok işe yararlar.