Merhabalar, bu makalemde C#’ta metot ve fonksiyon kullanımını anlatmaya çalışacağım. Aslında metot ve fonksiyon aynı şeydir diyebiliriz ve biz metot kelimesini kullanarak devam edeceğiz. Peki metot nedir?
DERS 8 : Metotlar ve Fonksiyonlar
Kısaca metot, sadece belirli bir işi yapan küçük programcıklardır. Örnek vermek gerekirse, bir program yazıyorsunuz ve içerisinde bir çok yerde faktöriyel hesabı yapmanız gerekiyor. Her seferinde faktöriyel hesaplama kodunu yazmak biraz anlamsız olurdu. O yüzden faktöriyel hesaplayan bir metot yazıyoruz ve gerekli yerlerde bu metodu çağırıyoruz. O zaman ilk metodumuz faktöriyel hesaplayan metot olsun ve bunu bir örnek programda kullanalım…
using System;
namespace ders8
{
class Program
{
static void Main(string[] args)
{
//Permutasyon hesaplama P(n,r)
Console.WriteLine("n değerini girin: ");
int n = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("r değerini girin: ");
int r = Convert.ToInt32(Console.ReadLine());
//P(n,r)=n!/(n-r)!
double permutation = CalculateFactorial(n) / CalculateFactorial(n - r);
Console.WriteLine("Sonuç: " + permutation);
Console.ReadKey();
}
static double CalculateFactorial(int value)
{
double result = 1;
for (int i = value; i > 0; i--)
{
result *= i;
}
return result;
}
}
}
Programın amacı permütasyon hesabı yapmak. Permütasyon, yukarıdaki kodda da yazdığım gibi n!/(n-r)! şeklinde hesaplanır. Gördüğünüz gibi burada iki defa faktöriyel hesabı yapmamız gerekiyor. Eğer metotlar olmasaydı, aynı kodu iki farklı değer için tekrar yazmamız gerekecekti. CalculateFactorial bir metottur. Metotlar yapı itibarıyla 4’e ayrılır: girdi alıp çıktı üretenler, girdi alıp çıktı üretmeyenler, girdi almayıp çıktı üretenler ve girdi almayıp çıktı da üretmeyenler. Bizim yazdığımız metot ilk gruba giriyor. “Girdi” kelimesi aslında ingilizce input kelimesi karşılığıdır; ancak metotlar için Türkçe’de girdi yerine parametre kelimesini kullanmak daha doğru olur. Çıktı yerine de metottan dönen değer tarzında bir şey kullanılabilir.
Metotlar, normal şartlarda sadece bir işi yerine getirmelidirler. İdeal kullanım budur. Yukarıda yazmış olduğumuz metot sadece faktöriyel hesapladığına göre bu metot ideal bir metottur. Bu metoda bir de ekrana yazdırma özelliği ekleseydik pek hoş olmazdı. O yüzden her metot tek bir iş yapmalı ve ismi de yaptığı iş olmalıdır. Size tavsiyem, az da olsa İngilizceniz varsa Türkçe program yazmayın derim. Bunun haricinde, metot isimlerinde kelimelerin ilk harflerini büyük yazın ve araya “_” işareti koymayın. En okunabilir yazım şekli budur. Ben de faktöriyel hesaplayan metoduma CalculateFactorial adını verdim (Türkçe olsaydı, FaktoriyelHesapla olacaktı).
Şimdi metodu nasıl yazdık açıklayalım. Her metodun bir imzası vardır. Bu imza nasıl oluşur? Metodun ismi ve aldığı parametreler metodun imzasıdır. Bu imza konusuna ilerde daha detaylı değineceğiz. Basit bir metot şu şekilde tanımlanır: <metodun_dönüş_tipi> MetotAdı (<parametre_listesi>). Metodun geri dönüş tipi herhangi bir tip olabilir: int, string, double, int[] vs. gibi. Bunun haricinde bir metot nesne veya liste de dönebilir (nesne ve liste konularını daha sonra göreceğiz). Metodun adı olarak içerisinde boşluk olmayan alfanümerik bir isim verebilirsiniz. Parametre listesi ise, metodun içinde ihtiyaç duyacağınız değerleri belirtir. Faktöriyel hesaplamak için neyin faktöriyelini hesaplayacağımızı bilmemiz gerekir, bunu parametre olarak dışarıdan alıyoruz. Parametre yazım şekli ise şu şekildedir: “tip degiskenAdi“. Yani örneğin: “int value“. Birden çok parametre geçmek istersek de: “int value, string name, double rate” şeklinde geçebiliriz.
Faktöriyel için dışarıdan parametremizi aldık, değişkenimizin adı value ve biz bunu içeride istediğimiz gibi kullanabiliriz. 5 satırlık bir kod ile faktöriyeli hesapladık ve sonucu result adlı değişkende tutuyoruz. Metodumuzun çalışması bittiğinde bu sonucu, metodu çağıran yere geri göndermemiz gerekli. Bu işlemi ise “return” anahtar sözcüğü ile gerçekleştiriyoruz. Buradaki önemli nokta, return edilen değişkenin tipi ile metodu tanımlarken yazmış olduğumuz metot dönüş tipinin aynı olması gerektiğidir. Kodda da gördüğünüz gibi metodu double belirttik, değişkeni de double tanımladık. Eğer metodunuzun bir geri dönüş değeri olmayacaksa, metodu tanımlarken geri dönüş tipi alanına “void” yazmalısınız ve metot içerisinde de sadece “return;” yazmalısınız.
Metodu yazdık ama nasıl çağıracağız? Çok basit, metodun adını yazıp parantez içinde de bizden beklediği parametreleri belirteceğiz. CalculateFactorial(5) gibi. O da bize 5’in faktöriyelini hesaplayıp geri döndürecek. Burada istersek dönüş değerini değişkene atayabiliriz: double fiveFactorial = CalculateFactorial(5); gibi. Ya da yukarıda benim yaptığım gibi geri dönüş değerini direkt olarak da kullanabilirsiniz. Metodun baş tarafındaki “static” anahtar sözcüğünden daha sonra bahsedeceğiz.
Parametreler metoda iki şekilde iletilebilir: değer (value) ve referans (reference) yöntemi ile. Aksi bir işlem yapmadıkça, tüm temel tipler değer olarak, tüm kompleks tipler de referans olarak metoda geçilirler. Peki nedir bunların farkı? Metoda değer ile geçtiğiniz parametreleri, metodun içerisinde değerini değiştirseniz bile, metodun dışına çıktığınızda değer eski haline döner. Referans ile geçilen parametre içeride değiştirilirse dışarıda da değişir. int, double, char gibi tipler değer olarak geçer; ancak örneğin int[] dizisi veya string referans olarak geçer. Değer ile parametre geçmenin örneğini hemen görelim:
static void Main(string[] args)
{
int number = 5;
Console.WriteLine(number);
ChangeNumber(number);
Console.WriteLine(number);
Console.ReadKey();
}
static void ChangeNumber(int value)
{
value = 8;
}
Programı çalıştırdığınızda ekrana iki kez, “5” yazacaktır. Değişken metodun içerisinde 8 olarak değiştirilmesine rağmen, metottan çıkınca yine 5 olacaktır; ancak aşağıdaki örnekte durum farklıdır:
static void Main(string[] args)
{
int[] number = { 5 };
Console.WriteLine(number[0]);
ChangeNumber(number);
Console.WriteLine(number[0]);
Console.ReadKey();
}
static void ChangeNumber(int[] value)
{
value[0] = 8;
}
Bu kodda ise number dizisinin ilk elemanı 5 iken, metot çağrımı sonrasında 8 olmaktadır. Peki biz ilk kodun da bu şekilde çalışmasını istersek ne yapmalıyız? Yani ben metoda int geçmek istiyorum ama içerde de değeri değişsin istiyorum. O zaman parametre kısmına “int value” yerine “ref int value” yazmamız gerekiyor, yani bu değişkeni referans olarak al dememiz gerekiyor. Aynı şekilde metodu çağırdığımız yerde de bu kelimeyi koymamız gerekiyor: ChangeNumber(ref number); gibi.
Son olarak bir de “out” anahtar kelimesi mevcut. Yazım şekli “ref” gibi olmakla beraber işlevi farklıdır. Genelde, bir metodun birden fazla çıktı üretmesi gerektiği durumlarda kullanılır. Örneğin bir bölme işlemi yapmak istiyoruz; ancak sonucun yanında kalanı da öğrenmek istiyoruz. O zaman aşağıdaki gibi bir kod yazmamız gerekiyor.
static void Main(string[] args)
{
int first = 10;
int second = 3;
int remain;
int divResult = Division(first, second, out remain);
Console.WriteLine(divResult + " " + remain);
Console.ReadKey();
}
static int Division(int x, int y, out int z)
{
int result = x / y;
z = x - (result * y);
return result;
}
Bu kodda, metot bize asıl bölme sonucunu döndürüyor, kalanı ise out ile belirtmiş olduğumuz değişkene atıyor. Bu arada, out ile gelen parametreye, metot içerisinde mutlaka bir değer atamalısınız, yoksa kodunuz derlenmeyecektir. Aynı şekilde metodun bir geri dönüş değeri olduğunu belirttiyseniz mutlaka return ile bir değer dönmeniz gerekecektir.
Bir sonraki makalemizde recursive yani öz yinelemeli metotları ve metotların aşırı yüklenmesini anlatmaya çalışacağım. Görüşmek üzere…