C# Fonksiyonlar ve C# Metotlar

C# fonksiyonlar

C# Fonksiyonlar, Şu ana kadar yaptığımız örneklerde alında farkında olmadan hazır bir fonksiyon olan ReadLine(), WriteLine() vb. gibi metotlar kullanıldı. Aslında bütün örneklerimizde birer c# fonksiyonu (diğer bir adı ise C# metodu) yaratmıştık. O da çalışabilir her programda bulunması gereken Main metoduydu. Artık Main metodu gibi başka metotlar yaratıp programımızın içinde kullanabileceğiz. Metotlar oluşturarak programımızı parçalara böler ve programımızın karmaşıklığını azaltırız. Ayrıca bazı kodları bir metot içine alıp aynı kodlara ihtiyacımız olduğunda bu metodu çağırabiliriz. Bu sayede de kod hamallığı yapmaktan kurtuluruz. Peki bir C# fonksiyonu nasıl oluşturulur?

Metot yaratımı ve kullanımı

int MetotAdi(int a,int b)
 {
 return a+b;
 }

Bu metot, iki tane int türünden girdi alır ve bu girdilerin toplamını int türünden tutar. Ancak bu metodu programımız içinde kullanabilmemiz için bu metodun içinde bulunduğu sınıf türünden bir nesne yaratıp “.” operatörüyle bu nesne üzerinden metodumuz erişmeliyiz.

 int Topla(int a,int b)
 {
 return a+b;
 }
 static void Main()
 {
 Metotlar nesne=new Metotlar();
 int a=nesne.Topla(2,5);
 Console.Write(a);
 }
 

HATIRLATMA

static olarak tanımlanan metotlara erişmek için metodun içinde bulunduğu sınıf türünden bir nesne yaratmaya gerek yoktur. static metot olarak tanımlanan metotlara sadece metodun adını yazarak erişilebilir.

static int Topla(int a,int b)
 {
 return a+b;
 }
 static void Main()
 {
 int a=Topla(2,5);
 Console.Write(a);
 }
 

– Bütün programlarda önce Main metodu çalışır. Diğer metotlar Main metodunun içinden çağrılmadıkça çalışmaz.
– Eğer metot, içinde bulunduğumuz sınıfta değil de, başka bir sınıf içinde yaratılmışsa o metodu kullanabilmek için önce sınıfı yazmamız gerekir.

class Metotlar1
 {
 public static int Topla(int a, int b)
 {
 return a + b;
 }
 }
 
class Metotlar2
 {
 static void Main()
 {
 int a = Metotlar1.Topla(2, 5);
 Console.Write(a);
 }
 }

Dikkat ettiyseniz bu metodun yaratılma satırının (4. satır) başına public anahtar sözcüğü konmuş. public sözcüğüyle derleyiciye bu metoda her sınıftan erişilebileceğini söylüyoruz. Eğer public sözcüğü yazılmamış olsaydı bu metoda sadece Metotlar1 sınıfından erişilebilirdi.

Şimdi de static olmayan bir metodu başka bir sınıf içinde yaratalım ve kullanalım:

class Metotlar1
 {
 public int Topla(int a, int b)
 {
 return a + b;
 }
 }
class Metotlar2
 {
 static void Main()
 {
 Metotlar1 nesne = new Metotlar1();
 int a = nesne.Topla(3, 9);
 Console.Write(a);
 }
 }

HATIRLATMA

Herhangi bir değer tutmayan (WriteLine gibi) metotları void anahtar sözcüğüyle yaratırız.

static void Yaz(object a, int b)
 { for (; b>0; b--)
 Console.Write(a);}
 static void Main()
 {
 Yaz("deneme", 5);
 }

ÖNEMLİ

Herhangi bir değer tutmayan metotlarda return; komutu, yanına herhangi bir ifade olmadan kullanılabilir. Aslında return; komutunun asıl görevi metottan çıkmaktır, ancak yanına bazı ifadeler koyularak metodun tuttuğu değeri belirtme vazifesi de görür. Örneğin bir if koşulu yaratıp, eğer koşul sağlanırsa metottan çıkılmasını, koşul sağlanmazsa başka komutlar da çalıştırılmasını sağlayabiliriz. Ancak doğal olarak bir metodun son satırında return; komutunun kullanılması gereksizdir.

static void Yaz(object a, int b)
 {
 if (b > 10)
 return;
 for (; b > 0; b--)
 Console.Write(a);
 }
 static void Main()
 {
 Yaz('n', 10);
 }

Bu programda eğer metoda verilen ikinci parametre 10’dan büyükse metottan hiçbir şey yapılmadan çıkılıyor.

METOTLARIN BAZI ÖZELLİKLERİ

C# Fonksiyonları kullanırken parametrelerini doğru sayıda, doğru sırada ve doğru türde vermeliyiz.
– Değer tutan metotlarda return satırıyla belirtilen ifade, metodu yaratırken verilen türle uyumlu olmalıdır.
– Değer tutmayan (void ile belirtilmiş) metotlarda return komutunun herhangi bir ifadeyle kullanılması yasaktır.
– Değer tutmayan C# metotları nın bir değermiş gibi kullanılması yasaktır.
– C# Metotları değer tutmayabileceği gibi, parametre de almayabilirler.

C# metotlar

static void Yaz()
 {
 Console.Write("deneme");
 }
static void Main()
 {
 Yaz();
 }

Buradaki ekrana “deneme” yazan metot herhangi bir parametre almaz. Dolayısıyla da programda kullanırken de parantezlerin içine hiçbir şey yazılmaz.

Bir metodun içinde başka bir metot yaratılamaz. Örneğin aşağıdaki gibi bir kullanım hatalıdır.

static void Yaz()
 {
 Console.Write("deneme");
 static void Ciz()
 {
 Console.Write("\n");
 }
 }
static void Main()
 {
 Yaz();
 }

ÖNEMLİ

C# Metodu yaratılırken ki metot parantezindeki değişkenlerin türleri tek tek belirtilmelidir. Virgül ile ortak tür belirtimi yapılamaz.

Yani,

static void Ornek(int a,int b)

yerine

static void Ornek(int a, b) //yazılamaz.

Metot parametresi olarak diziler

C# fonksiyonlarına dizi gönderme yapılabildiği gibi bir C# fonksiyonu geriye dizi döndürme de sağlanabilir.

static void Yaz(int[] dizi)
 {
 foreach (int i in dizi)
 Console.WriteLine(i);
 }
 static void Main()
 {
 int[] dizi = { 1, 2, 4, 7, 9 };
 Yaz(dizi);
 }

Buradaki Yaz metodu kendisine parametre olarak verilen dizinin elemanlarını alt alta yazdı. Eğer yalnızca int[] türündeki değil bütün türlerdeki dizileri ekrana yazan bir metot yazmak istiyorsak;

static void Yaz(Array dizi)
 {
 foreach (object i in dizi)
 Console.WriteLine(i);
 }
 static void Main()
 {
 int[] dizi = { 1, 2, 4, 7, 9 };
 Yaz(dizi);
 }

Dizi ve değişken parametreler arasındaki fark

Dizi ve değişken parametreler arasındaki fark içi aşağıdaki programların çıktılarını kontrol ediniz.

Dizi olarak parametre gönderilen bir metot.

static void Degistir(int[] dizi)
 {
 for (int i = 0; i < 5; i++)
 dizi[i] = 10;
 }
 static void Yaz(Array dizi)
 {
 foreach (object a in dizi)
 Console.WriteLine(a);
 }
 static void Main()
 {
 int[] dizi = { 1, 2, 4, 7, 8 };
 Degistir(dizi);
 Yaz(dizi);
 }

Değişken olarak parametre gönderilen bir metot.

static void Degistir(int sayi)
 {
 sayi = 10;
 }
 static void Yaz(int sayi)
 {
 Console.WriteLine(sayi);
 }
 static void Main()
 {
 int sayi = 1;
 Degistir(sayi);
 Yaz(sayi);
 }

Bu iki programı çalıştırdığınızda göreceksiniz ki metoda parametre olarak aktarılan dizinin metot içinde bir elemanının değiştirilmesi esas diziyi etkiliyor. Ancak metoda parametre olarak aktarılan değişkenin metot içinde değiştirilmesi esas değişkeni etkilemiyor. Çünkü bir metoda parametre olarak bir dizi verildiğinde derleyici metoda dizinin bellekteki adresini verir; metot o adresteki verilerle çalışır. Dolayısıyla da dizinin herhangi bir elemanındaki değişiklik esas diziyi etkileyecektir. Çünkü gerek esas program, gerekse de metot aynı adresteki verilere erişir. Halbuki bir metoda parametre olarak bir değişken verdiğimizde metot için değişkenin bellekteki adresi önemli değildir, metot için önemli olan değişkenin değeridir. Metot, değişkeni kullanabilmek için geçici bir bellek bölgesi yaratır ve parametre olarak aldığı değişkenin değerini bu geçici bellek bölgesine kopyalar ve o geçici bellek bölgesiyle çalışır. Metottan çıkıldığında da o geçici bellek bölgesi silinir.

Peki bir metoda aktarılan bir değişkende yapılan bir değişikliğin tıpkı dizilerdeki gibi esas değişkeni etkilemesini ister miydiniz?

İşte bunun için C#’ın ref ve out olmak üzere iki anahtar sözcüğü vardır.

ref anahtar sözcüğü

static void Degistir(ref int sayi)
 {
 sayi = 10;
 }
 static void Yaz(int sayi)
 {
 Console.WriteLine(sayi);
 }
 static void Main()
 {
 int sayi = 1;
 Degistir(ref sayi);
 Yaz(sayi);
 }

ref anahtar sözcüğü değişkenlerin metotlara adres gösterme yoluyla aktarılmasını sağlar. Gördüğünüz gibi ref sözcüğünün hem metodu çağırırken , hem de metodu yaratırken değişkenden önce yazılması gerekiyor. Bu program ekrana 10 yazacaktır. Ayrıca ref sözcüğüyle bir değişkenin metoda adres gösterme yoluyla aktarılabilmesi için esas programda değişkene bir ilk değer verilmelidir. Yoksa program hata verir.

out anahtar sözcüğü

Kullanımı ref anahtar sözcüğüyle tamamen aynıdır. Tek farkı out ile belirtilen değişkenlere esas programda bir ilk değer verilmesinin zorunlu olmamasıdır. Örneğin aşağıdaki kullanım tamamen doğrudur.

static void Degistir(out int sayi)
 {
 sayi = 10;
 }
 static void Yaz(int sayi)
 {
 Console.WriteLine(sayi);
 }
 static void Main()
 {
 int sayi;
 // ref de ilk değer verilmesi gerekir.
 Degistir(out sayi);
 Yaz(sayi);
 }

ÖNEMLİ

ref sözcüğünün dizilerle kullanımı gereksiz olmasına rağmen C# bunu kısıtlamamıştır. Ancak out sözcüğü dizilerle kullanılamaz.

C# Metotlarının aşırı yüklenmesi

C#’ta parametre sayısı ve/veya parametrelerin türleri farklı olmak şartıyla aynı isimli birden fazla metot yaratılabilir. Buna metotların aşırı yüklenmesi denir.

C#, bir metot çağrıldığında ve çağrılan metot aynı isimli birden fazla metot bulunduğunda metodun çağrılış biçimine bakar. Yani ana programdaki metoda girilen parametrelerle yaratılmış olan metotların parametrelerini kıyaslar. Önce parametre sayısına bakar. Eğer aynı isimli ve aynı sayıda parametreli birden fazla metot varsa bu sefer parametre türlerinde tam uyumluluk arar, parametre türlerinin tam uyumlu olduğu bir metot bulamazsa bilinçsiz tür dönüşümünün mümkün olduğu bir metot arar, onu da bulamazsa programımız hata verir.

static void Metot1(int x, int y)
 {
 Console.WriteLine("1. metot çağrıldı.");
 }
 static void Metot1(float x, float y)
 {
 Console.WriteLine("2. metot çağrıldı.");
 }
 static void Metot1(string x, string y)
 {
 Console.WriteLine("3. metot çağrıldı.");
 }
 static void Main()
 {
 Metot1("deneme", "deneme");
 Metot1(5, 6);
 Metot1(10f, 56f);
 }

Bu programda üç metot da aynı sayıda parametre almış. Bu durumda parametrelerin türlerine bakılır. Ana programdaki Metot1(“deneme”,”deneme”); satırıyla üçüncü metot çağrılır. Metot1(5,6); metot çağrımının parametre türlerinin tam uyumlu olduğu metot birinci metottur, o yüzden birinci metot çağrılır. Eğer birinci metot yaratılmamış olsaydı ikinci metot çağrılacaktı. Son olarak Metot1(10f,56f); satırıyla da ikinci metot çağrılır.

static void Metot1(float x, float y)
 {
 Console.WriteLine("1. metot çağrıldı.");
 }
 static void Metot1(double x, double y)
 {
 Console.WriteLine("2. metot çağrıldı.");
 }
 static void Main()
 {
 Metot1(5, 6);
 }

Yukarıdaki programda iki metodun da parametre sayısı eşit, iki metotta da tam tür uyumu yok ve iki metotta da bilinçsiz tür dönüşümü mümkün. Bu durumda en az kapasiteli türlü metot çağrılır. Yani bu programda birinci metot çağrılır.

static void Metot1(float x, float y)
 {
 Console.WriteLine("1. metot çağrıldı.");
 }
 static void Metot1(int x, int y)
 {
 Console.WriteLine("2. metot çağrıldı.");
 }
 static void Main()
 {
 Metot1(5, 6.4f);
 }

Bu durumda birinci metot çağrılır.

static void Metot1(float x, float y)
 {
 Console.WriteLine("1. metot çağrıldı.");
 }
 static void Metot1(int x, int y)
 {
 Console.WriteLine("2. metot çağrıldı.");
 }
 static void Main()
 {
 Metot1('f', 'g');
 }

Bu durumda ikinci metot çağrılır. Çünkü char hem inte hem de floata bilinçsiz olarak dönüşebilir. Ancak int daha az kapasitelidir.

Değişken sayıda parametre alan C# fonksiyonlar

Şimdiye kadar metotlarımıza gönderdiğimiz parametre sayısı belliydi ve bu parametre sayısından farklı bir miktarda parametre girersek programımız hata veriyordu. Artık istediğimiz sayıda parametre girebileceğimiz metotlar yapmasını göreceğiz.

static int Toplam(params int[] sayilar)
 {
 if (sayilar.Length == 0)
 return 0;
 int toplam = 0;
 foreach (int i in sayilar)
 toplam += i;
 return toplam;
 }
 static void Main()
 {
 Console.WriteLine(Toplam());
 Console.WriteLine(Toplam(5));
 Console.WriteLine(Toplam(5, 10));
 Console.WriteLine(Toplam(2, 9, 12));
 Console.WriteLine(Toplam(7, 12, 45));
 Console.Write(Toplam(123,12,5,7,9,4,12));}

Burada aldığı parametrelerin toplamını tutan bir C# metodu yazdık. Eğer metoda hiç parametre girilmemiş ise 0 değerini döndürmektedir.
Gördüğünüz gibi C# fonksiyonlar’ ında params anahtar sözcüğüyle girilen tüm parametreleri int[] türündeki sayilar dizisine aktardık ve bu diziyi metotta gönlümüzce kullandık. Bir de bu programımızda Length özelliğini gördünüz. Özellikler metotlara benzerler, metotlardan tek farkları “()” kısımları olmamasıdır. Dolayısıyla parametre almazlar. Örneğimizde sayilar. Length satırı sayilar dizisinin eleman sayısını int türünden tutar.

static int Islem(string a, params int[] sayilar)
 {
 if (a == "carp")
 {
 if (sayilar.Length == 0)
 return 1;
 int carpim = 1;
 foreach (int i in sayilar)
 carpim *= i;
 return carpim;
 }
 else if (a == "topla")
 {
 if (sayilar.Length == 0)
 return 0;
 int toplam = 0;
 foreach (int i in sayilar)
 toplam += i;
 return toplam;
 }
 else
 return 0;
 }
 static void Main()
 {
 Console.WriteLine(Islem("topla",3,4,7,8));
 Console.WriteLine(Islem("carp", 5,23,6));
 }

Bu programdaki gibi metodumuzda değişken parametre yanında bir ya da daha fazla normal sabit parametre de olabilir. Ancak değişken parametre mutlaka en sonda yazılmalıdır.

ÖNEMLİ

Değer döndüren metotlarımız mutlaka her durumda değer döndürmelidir. Örneğin metodumuzda sondaki else kullanılmazsa programımız derlenmez. Çünkü else’i kullanmasaydık birinci parametre yalnızca “carp” veya “topla” olduğunda metodumuz bir değer döndürecekti. Ve bu da C# kurallarına aykırı.

C# fonksiyonlar ÖRNEK – 1
Parametresi ve deri dönüş değeri olmayan ekrana Merhaba yazan MerhabaYaz isminde metodu tanımlayınız.

C# fonksiyonlar ÖRNEK – 2
Gönderilen iki sayıdan büyük olanı geri gönderen metodu oluşturunuz.

C# fonksiyonlar ÖRNEK – 3
Girilen sayının tekmi çiftmi olduğunu bulduran programI metot kullanarak yazınız.

ÖRNEK – 1 ÇÖZÜMÜ

static void MerhabaYaz(){
 Console.WriteLine("Merhaba");}
 static void Main(string[] args){ MerhabaYaz();
 Console.ReadKey();}

ÖRNEK – 2 ÇÖZÜMÜ

private static int BUYUK(int sayi1, int sayi2){
 if (sayi1 > sayi2)
 return sayi1;
 else if (sayi2 > sayi1)
 return sayi2;
 else
 return sayi1;
 }
 static void Main(string[] args)
 {
 Console.Write("Bir sayı giriniz");
 int s1 = int.Parse(Console.ReadLine());
 Console.Write("Bir sayı daha giriniz");
 int s2 = int.Parse(Console.ReadLine());
 Console.Write(BUYUK(s1, s2));
 Console.ReadKey();
 }

ÖRNEK – 3 ÇÖZÜMÜ

static bool tekcift(int sayi)
 {
 bool durum;
 if (sayi % 2 == 0)
 durum = true;
 else
 durum = false;
 return durum;
 }
 static void Main(string[] args)
 {
 int s1;
 bool drm;
 Console.Write("Sayıyı Giriniz..:");
 s1 = Convert.ToInt32(Console.ReadLine());
 drm = tekcift(s1);
 if (drm == true)
 Console.Write("Sayı Çift");
 else
 Console.Write("Sayı Tek");
 Console.ReadKey();}

Evet değerli arkadaşlar böylece C# fonksiyonlar başlıklı bir yazımızın daha sonu gelmiş olduk. Unutmayınız ki C# Fonksiyonlar konusu programlamanın en temel konularından birini oluşturmaktadır. Bu konuya hakimiyetiniz sizlerin bir çok noktada fazladan kod yazma zahmetinden kurtaracaktır. C# dersleri ile hakkında aklına takılanları yazmaktan çekinmeyin.

Dilerseniz bir önceki yazımız olan C# Diziler konusuna bir göz atabilirsiniz.

Kodyaz.NET Ana Sayfasına Dön