Delegate Nedir?



C# programlama dilinde tanımlanan ve metot olarak adlandırılan iÅŸlevlerin bellek adresini tutmak için kullanılan yapıya delegate veya temsilci denir. C# delegate yapısı C/C++ dillerindeki function pointer veya fonksiyon göstericileri yapısına benzemektedir. 

Metot adı ve parametresi metot imzası olarak adlandırılır.

Bellekte bulunan metotlara erişebilmek için metot imzasının bilinmesi gerekir. Bu metot imzası C# içerisinde yer alan delegate ile tanımlanır.

Metotların sabit bir tanımı yoktur. Aşağıdaki iki metot birbirinden farklıdır:

void Topla(int sayi1, double sayi2); 
void Topla(double sayi1, int sayi2);

Metot adı ve parametresi metot imzası olarak adlandırılır.

Delegate Kullanımı


Genel tanımı aşağıdaki gibidir:

delegate <Metot_Dönüş_Değeri> <Temsilci_Adı> (<Metot_Parametresi>);

Yukarıda tanımlanan ilk metoda erişmek için aşağıdaki gibi bir delegate tanımı yapılmalıdır:

delegate void Temsilci (int sayi1,int sayi2);

Oluşturulan bu temsilci sayesinde bu imzaya sahip metotlara erişilebilir. Metotlara erişimi aşağıdaki gibidir:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace @delegate
{
class Program
{
static void Sum(int number1, double number2)
{
Console.WriteLine("Number1: {0} + Number2: {1} = result {2}", number1, number2, number1 + number2);
}
delegate void sumDelegate(int x, double y);
static void Main(string[] args)
{
sumDelegate sum = Sum; // sumDelegate sum = new sumDelegate(Topla);
sum(3, 5);
Console.ReadLine();
}
}
}


Func Delegate

Sıfır veya daha fazla input alır ve bir tane output verir. 

public delegate TResult Func < in T,out TResult>(T arg);

Örnek:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace @delegate
{
class Program
{
static int Sum(int num1, int num2)
{
return num1 + num2;
}
static void Main(string[] args)
{
Func<int, int, int> add = Sum;
int result = add(3, 5);
Console.WriteLine(result);
Console.ReadLine();
}
}
}


Action Delegate

Bir değer döndürmez, bunun dışından func delegate ile aynıdır.

public delegate void Print (int val);

Örnek:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace @delegate
{
class Program
{
static void ConsolePrint(int num)
{
Console.WriteLine(num);
}
static void Main(string[] args)
{
Action<int> printCns = ConsolePrint;
printCns(5);
Console.ReadLine();
}
}
}

Func ve Action Delegate Avantajları 

  1. Tanımlamak hızlı ve kolaydır. 
  2. Uygulama boyunca uyumlu tip.
  3. Kodu kısadır.


Kaynak:
Ders notları
https://docs.microsoft.com/tr-tr/dotnet/api/system.action-1?view=net-6.0
https://www.yusufsezer.com.tr/csharp-delegate/
https://docs.microsoft.com/tr-tr/dotnet/api/system.func-2?view=net-6.0






Bu bölüm en eÄŸlenceli bölümlerden birisi. Bu bölümde kendi fonksiyonlarımızı yazacağız. Yani modüler programlamaya giriÅŸ yapacağız.  Hadi baÅŸlayalım.

Fonksiyon Nedir?


C'de altprogramlara fonksiyon denir. Her fonksiyon faydalı bir takım iÅŸlemleri yerine getirmek için tasarlanır ve çaÄŸrılır. Fonksiyonların, onları çağıran fonksiyonlardan altıkları girdileri ve yine onları çağıran fonksiyonlara gönderdikleri çıktıları vardır. 

Fonksiyonlar bir programı modüllere ayırmamıza izin verir. Fonksiyon tanımlarında tanımlanan tüm değişkenler yerel değişkenlerdir (yalnızca içerisinde tanımlandıkları fonksiyon içinde erişilebilirler).


Fonksiyon Tanımlamaları 

C'de fonksiyon tanımlama işleminin genel biçimi şöyledir:

[geri dönüş deÄŸerinin türü] <Fonksiyonun İsmi> ([Parametreler]) 
{
...
}

Yukarıdaki gösterimde <...> ile gösterilen ifadeler zorunlu olarak bulunması gerekenleri; [...] bulunması zorunlu olmayan, isteğe bağlı ifadeleri göstermektedir. Örneğin:

float fonk(){
    .   
    .
    .
}


Yukarıdaki fonksiyonun geri dönüş değerinin float olduğunu ve parametre almadığını görüyoruz.

Bir fonksiyonun parametresi ve/veya geri dönüş değeri olmayabilir. Parametresiz fonksiyonlarda fonksiyon parantezleri içine ya hiçbir şey yazılmaz ya da void anahtar sözcüğü yazılır. Örneğin:

float a1(void){                    float a1(){
    .                                  .
    .                                  .
    .                                  .
}                                  }


Yukarıdaki iki tanımlama biçiminde de a1 fonksiyonunun parametresiz olduÄŸu anlatılmaktadır, dolayısıyla eÅŸdeÄŸerdir.

Fonksiyon tanımlanırken geri dönüş değerinin türü yerine hiçbir şey yazılmazsa C derleyicisi geri dönüş değerinin türünün int olduğunu varsayar. Örneğin:

y1(){
    .   
    .    
    .
}

y1 fonksiyonunun parametresi yoktur; ancak geri dönüş deÄŸeri int türündendir. 


   ! C'de  fonksiyon içinde fonksiyon tanımlanmaz.. !


float fonk1(){
    ...
    int fonk2(){
        ...            /* Hatalı tanımlama */
    }
    ...
}

Yukarıdaki tanımlamada fonk2 'nin fonk1'in içinde tanımlandığını görüyoruz; bu nedenle tanımlama işlemi geçersizdir. İki fonksiyonun aşağıdaki örnekte olduğu gibi tanımlanması gerekmektedir:

float fonk1(){
    .
    .
    .
}

int fonk2(){
    .   
    .    
    .
}



Fonksiyonların Çağrılması


Bir fonksiyon çağrıldığında programın akışı fonksiyonu çalıştırmak üzere bellekte fonksiyon kodunun bulunduğu böyleye atlar; fonksiyonun çalışma işlemi bittikten sonra da akış tekrar çağıran fonksiyonun kalınan yerinden devam eder.


Fonksiyonlar ancak tanımlanmış fonksiyonların içerisinde çağrılabilirler. Örneğin:

main(){
    int a = 100, b =200;    
    printf("a= %d b = %d\n",a,b);
}
printf("merhaba\n"); // hata ! Burada fonksiyon çağrılmaz

fonk(){
    int x = 10, y = 20;
    printf("x= %d y = %d\n",x,y);
}


Burada printf, main ve fonk isimleri fonksiyonların içinde doÄŸru biçimde çaÄŸrılmıştır. Ancak iki fonksiyonun arasında hiçbirinin içinde olmayacak biçimde çaÄŸrılmış olan: printf("merhaba\n"); geçersizdir. 

Örnekler:


1) Girilen iki sayıyı toplayan program:

#include <stdio.h>
int addNumbers(int a, int b);         // function prototype

int main()
{
    int n1,n2,sum;

    printf("Enters two numbers: ");
    scanf("%d %d",&n1,&n2);

    sum = addNumbers(n1, n2);        // function call
    printf("sum = %d",sum);

    return 0;
}

int addNumbers(int a, int b)         // function definition   
{
    int result;
    result = a+b;
    return result;                  // return statement
}


Ekran Çıktısı:

Enters two numbers: 2
3
sum = 5

2) Girilen sayının karesini al program:

#include<stdio.h>  
int kareal(int);  
void main()  
{  
    int sayi, kare;
    printf("Karesi alınacak olan sayiyi girinizi: ");  
    scanf("%d",&sayi);
    kare = kareal(sayi);
    printf("%d sayisinin karesi = %d\n",sayi,kare);
    
    
}  
int kareal(int sayi)  
{  
    return sayi*sayi;  
}  


Ekran Çıktısı:

Karesi alınacak olan sayiyi girinizi: 3
3 sayisinin karesi = 9

3) Girilen sayının tek mi çift mi olduğunu bulan program

#include<stdio.h>  
int cift_tek(int);  
void main()  
{  
 int n,flag=0;  
 printf("\ngirilen sayinin tek mi cift mi ?");  
 printf("\nsayi giriniz: ");  
 scanf("%d",&n);  
 flag = cift_tek(n);  
 if(flag == 0)  
 {  
    printf("\nsayi tek");  
 }  
 else   
 {  
    printf("\nsayi cift");  
 }  
}  
int cift_tek(int n)  
{  
    if(n%2 == 0)  
    {  
        return 1;  
    }  
    else   
    {  
        return 0;  
    }  
}

Ekran Çıktısı:

girilen sayinin tek mi cift mi ?
sayi giriniz: 3
sayi tek

4) İki değerin yerini değiştiren program (swap):

#include<stdio.h>
// function prototype, also called function declaration
void swap(int a, int b);          
 
int main()
{
    int m = 22, n = 44;
    // calling swap function by value
    printf(" values before swap  m = %d \nand n = %d", m, n);
    swap(m, n);                         
}
 
void swap(int a, int b)
    int tmp;
    tmp = a;
    a = b;
    b = tmp;
    printf(" \nvalues after swap m = %d\n and n = %d", a, b);
}

Ekran Çıktısı:

values before swap  m = 22 
and n = 44 
values after swap m = 44
 and n = 22


5) Bir dizi döndürecek fonksiyon kullanarak bazı değerlerin maksimum ve minimumunu bulan program: ( bu örnekte pointer kullanılmıştır. İlerleyen konularda pointerlara değineceğiz.)

# include <stdio.h>
# define max 10
int *maxmin(int ar[], int v);
int main()
{
  int  arr[max];
int n,i, *p;
  printf("Number of values you want to input: ");
  scanf("%d",&n);
  printf("Input %d values\n", n);
  for(i=0;i<n;i++)
    scanf("%d",&arr[i]);
  p=maxmin(arr,n);
printf("Minimum value is: %d\n",*p++);
printf("Maximum value is: %d\n",*p);
}
int *maxmin(int arra1[], int v)
{
  int i;
static int result_mm[2];
result_mm[0]=arra1[0];
result_mm[1]=arra1[0];
for (i=1;i<v;i++)
{
if(result_mm[0] > arra1[i])
    result_mm[0]=arra1[i];
if(result_mm[1]< arra1[i])
  result_mm[1]= arra1[i];
}
return result_mm;
}

Ekran Çıktısı:

Number of values you want to input: 4
Input 4 values
3
5
7
8
Minimum value is: 3
Maximum value is: 8












Kaynaklar:

A'dan Z'ye C Programlama Kılavuzu
https://www.programiz.com/c-programming/c-functions
https://www.javatpoint.com/functions-in-c
https://fresh2refresh.com/c-programming/c-function/
https://www.w3resource.com/c-programming-exercises/function/index.php