Tag Archives: method

C# Delegate Tipine Genel Bir Bakış

Bir delegate tipi, özel parametre listesi ve geri dönüş tipi ile birlikte bir metoda referans bildirir. Böylece bir delegate tipi oluşturursak bir metoda referans içeren bir nesne yaratmış oluyoruz. Bu metod ise bu referans ile çağırılabilir konuma gelmiş oluyor.

Aşağıdaki örneğimiz bir Fonksiyon adında bir delegate tanımlar ve onu kullanır;

using System;

namespace ConsoleApplication1
{
 delegate double Fonksiyon (double d);

class Carpma
 {
 double carpim;

public Carpma(double carpim)
 {
 this.carpim = carpim;
 }

public double Carp(double x)
 {
 return x * carpim;
 }
 }

class Test
 {
 static double Kare(double x)
 {
 return x * x;
 }

static double[] Uygula(double[] a, Fonksiyon f)
 {
 double[] sonuc = new double[a.Length];

for (int i = 0; i < a.Length; i++)
 sonuc[i] = f(a[i]);

return sonuc;
 }

static void Main()
 {
 double[] a = { 0.0, 0.5, 1.0 };

double[] kareler = Uygula(a, Kare);

double[] sinusler = Uygula(a, Math.Sin);

Carpma c = new Carpma(2.0);
 double[] ciftler = Uygula(a, c.Carp);
 }
 }

}

Fonksiyon delegate tipinin örneği double tipinde argüman alan ve geriye double türünde bir veri döndüren herhangi bir metoda referans olabilir. Uygula() metodu verilen Fonksiyon’u double[] ile uygular ve geriye bir double[] sonucunu döndürür. Main metodu içerisinde, Uygula 3 farklı fonksiyonu double[] ile uygular.

Bir delegate, bir statik metoda (Kare ve Math.Sin metodları gibi) ya da bir metod örneğine (c.Carp metodu gibi)referans olabilir.

Bir metod örneğine referans olan bir delegate, belirli bir nesne örneğine de referans olabilir. Ve bu metod örneği delegate ile çağırıldığında, bu nesne this ile birlikte yönelir.

Bir delegate örneği yaratmak için, bir metodu delegate değişkenine atayabiliriz:

using System;

namespace ConsoleApplication1
{
 delegate int Donusturme (int x);

class Test
 {
 static int Kare (int x)
 {
 return x * x;
 }

static void Main()
 {
 Donusturme d = Kare; //Delegate örneği oluşturma
 int sonuc = d(3); //Delegate'i çağır
 Console.WriteLine(sonuc); //9
 }
 }

}

Görüldüğü üzere, bir delegate örneği çağırmak, tıpkı bir metod çağırımına benzer. (d(3) gibi) Bu arada;

 Donusturme d = Kare; 

satırı aşağıdaki kodun kısaltılmış halidir;

Donusturme d = new Donusturme (Kare);</p>  <p>d(3)

kodumuz da

d.Invoke(3)

kodunun kısaltılmışıdır.

Delegate Uyumlu Metodlar Yazmak

Bir delegate değişkeni metodlara dimanik olarak atanır. Bu delegate uyumlu metod yazmanın anahtarıdır. Aşağıdaki örnekte, Donustur adından bir yardımcı metodumuz var ve bir dizinin elemanlarını karelerine dönüştürür:

using System;

namespace ConsoleApplication1
{
 delegate int Donusturme (int x);

class Yardımcı
 {
 public static void Donustur(int[] degerler, Donusturme d)
 {
 for (int i = 0; i < degerler.Length; i++)
 degerler[i] = d(degerler[i]);
 }
 }

 class Test
 {
 static int Kare (int x)
 {
 return x * x;
 }

static void Main()
 {
 int[] degerler = { 1, 2, 3 };
 Yardımcı.Donustur(degerler, Kare);

foreach (int i in degerler)
 Console.Write(i + " "); // 1 4 9
 }
 }
}

Her delegate örneği çoklu kullanım yeteneğine sahiptir. Bunun anlamı; bir delegate örneği sadece tek bir metoda referans değil, birden fazla metoda referans olabilir. + ve += operatörleri delegate örneklerini birleştirir. Örneğin:

 DelegateOrnek d = MetodOrnek;</p>  <p>d += FarklıMetodOrnek; 

Bu durumda d delegate’ini çağırmak bu iki metodu çağırmak anlamına gelir. Eklenilme sırasına göre delegate tipleri çağırılır.

– ve –= operatörleri de sağıdaki metodu solundaki delegate örneğinden silerler. Örneğin;

 d –= MetodOrnek; 

Bu durumda d delegate’ini çağırmak sadece FarklıMetodOrnek metodunu çağırmamız anlamına gelir.

NOT: Delegate tipleri immutable tiplerdir. Bunun anlamı += veya –= operatörlerini kullandığınızda yeni bir delegate örneği oluşturmuş olursunuz ve varolan değişkeni ona atarsınız.

Çoklu gönderilen bir delegate tipi eğer void olmayan bir geri dönüş tipine sahipse, çağıran bu delegate’in içerdiği son metodun geri dönüş değerini alır. Önde bulunan metodlar yine de çağırılır fakat bunların geri dönüş değerleri görmezden gelinir.

NOT: Tüm delegate tipleri dolaylı olarak System.MulticastDelegate sınıfından türetilir. O da System.Delegate sınıfından kalıtım alır. += ve –= operatörlerini kullandığımızda aslında System.Delegate sınıfının statik tanımlanmış Combine ve Remove metodlarını kullanmış oluruz.

Statik Metod vs Metod Örneği

Bir delegate nesnesi bir metod örneğine atandığında, sadece atandığı metod olan referansı değil, ayrıca ait olduğu metodu da korur. System.Delegate sınıfının Target özelliği bu örneği gösterir. Örneğin;

using System;

namespace ConsoleApplication1
{
 public delegate void İlerleme (int TamamlanmaYuzdesi);

class Test
 {
 static void Main()
 {
 Ornek o = new Ornek();
 İlerleme i = o.İlerlemeOrnek;
 i(90); // 90
 Console.WriteLine(i.Target == o); // True
 Console.WriteLine(i.Method); // Void İlerlemeOrnek(Int32)
 }
 }

class Ornek
 {
 public void İlerlemeOrnek(int TamamlanmaYuzdesi)
 {
 Console.WriteLine(TamamlanmaYuzdesi);
 }
 }
}

Generic Delegate Tipleri

Bir delegate tipi generic tipinde parametreler içerebilir. Örneğin;

public delegate T Donusturme<T> (T arg);

Bu tanımlama ile, Donustur yardımcı metodunu herhangi bir tip ile kullanabiliriz:

 public class Yardımcı
 {
 public static void Donustur<T> (T[] degerler, Donusturme<T> t)
 {
 for (int i = 0; i < degerler.Length; i++)
 degerler[i] = t(degerler[i]);
 }
 } 

Func ve Action Delegate’leri

Generic delegate’ler ile, herhangi bir geri dönüş tipi ve herhangi sayıda argümanı olan metodlar için küçük delegate tipleri oluşturmak mümkündür. Bu delegate tiplerinden olan Func ve Action delegate’leri System namespace’i içerisinde yer alır.

 delegate Sonuc func<out Sonuc>();
 delegate Sonuc func<in T, out Sonuc>(T arg);

delegate void Action ();
 delegate void Action<in T>(T arg); 

Bir önceki örneğimizde Donustur delegate örneğini, sadece basit bir T argümanı alan ve aynı cinsten bir değer geri döndüren Func delegate’i ile yer değiştirebiliriz:

 public static void Donustur<T> (T[] degerler, Func <T, T> donus)
{
 for (int i = 0; i < degerler.Length; i++)
 degerler[i] = donus (degerler[i]);
} 

Delegate  Uyumluluğu

Tip

Tüm delegate tipleri, imzaları aynı olsa bile birbiri ile uyuşmayan tiplerdir.

 delegate void D1();
 delegate void D2();

D1 d1 = Metod1;
 D2 d2 = d1; // Derleme zamanı hatası 

Aşağıdaki örnek ise herhangi bir hata vermez:

 D2 d2 = new D2 (d1); 

Delegate örnekleri eğer aynı metodlara hedef gösterilirse bunlar eşit olarak nitelendirilir. Örneğin:

 delegate void D();
 ...
 D d1 = Metod1;
 D d2 = Metod1;
 Console.WriteLine (d1 == d2); // True döndürür. 

Birden fazla metoda referans gösteren delegate tipleri, eğer aynı metodlar aynı sırayla ise bu tipler de eşit olarak nitelendirir.

Parametre

Bir delegate tipi, hedef gösterdiği metodtan daha belirli parametre tiplerine sahip olabilir. Bu duruma contravariance adı verilir. Örneğin;

 using System;

namespace ConsoleApplication1
{
 delegate void StringEtki (string s);

class Test
 {
 static void Main()
 {
 StringEtki se = new StringEtki(NesneEtki);
 se("Merhaba");
 }
 static void NesneEtki(object o)
 {
 Console.WriteLine(o);
 }
 }
} 

Bu örneğimizde, StringEtki delegate tipi string tipindeki bir argüman ile çağırılır. Ve bu argüman hedef metoda aktarıldığında, bu argüman dolaylı olarak object tipine çevrilir (üst tipi olduğundan).

Geri Dönüş

Delegate’in geri dönüş tipi hedeflediği metodun geri dönüş tipinden daha az belirli olabilir. Bu duruma da covariance adı verilir. Örneğin;

 using System;

namespace ConsoleApplication1
{
 delegate object NesneGetir ();

class Test
 {
 static string StringGetir()
 {
 return "Merhaba";
 }
 static void Main()
 {
 NesneGetir o = new NesneGetir(StringGetir);
 object sonuc = o();
 Console.WriteLine(sonuc); //Merhaba
 }
 }
} 

NesneGetir geriye bir object döndürmesi bekler, fakat object alt sınıfı bunu ayrıca yapar. Delegate’in geri dönüş tipi “covariant”’tir.

C#’ta Method Aşırı Yüklemek

C#’ta method aşırı yüklenmesi, method imzaları farklı olan aynı isimdeki methodları aynı sınıf içerisinde kullanıma izin verir. Aşırı yükleme mekanizması, parametrelere uygun eşleşen methodu bulur ya da herhangi bir basit eşleşme olmazsa bir hata üretir. Aşağıdaki örnek, arışı yükleme mekanizmasının nasıl çalıştığına bir örnektir. Main() methodunun içinde hangi methodun çağrılacağını yorum olarak yazdım.

using System;
using System.Collections;
using System.Linq;
using System.Text;

namespace HelloWorld
{
class Test
{
static void A()
{
Console.WriteLine("A()");
}
static void A(object x)
{
Console.WriteLine("A(object x)");
}
static void A(int x)
{
Console.WriteLine("A(int x)");
}
static void A(double x)
{
Console.WriteLine("A(double x)");
}
static void A<T>(T x)
{
Console.WriteLine("A<T>(T x)");
}
static void A(double x, double y)
{
Console.WriteLine("A(double x, double y)");
}
static void Main()
{
A();          // Çağırılan F()
A(1);         // Çağırılan F(int)
A(1.0);       // Çağırılan F(double)
A("abc");     // Çağırılan F(object)
A((double)1); // Çağırılan F(double)
A((object)1); // Çağırılan F(object)
A<int>(1);    // Çağırılan F<T>(T)
A(1, 1);      // Çağırılan F(double, double)
}
}
}

Önemli: Method aşırı yükleme yanlış kullanımlara neden olabilir. Genel olarak bakarsak, method yüklemeyi sadece methodların hepsi anlamsal olarak aynı işi yaptığı zamanda kullanmalıyız. Bir çok yazılımcı, bu olayı “tek bir method farklı argümanlara sahip” olabilir şeklinde düşünür. Aslında, yerel değişkenin, parametrenin veya özelliğin tipini değiştirme, farklı yüklemelerin çağırılmasına neden olabilir. Yazılımcılar method aşırı yüklemesinin yan etkisini göremeyebilirler. Fakat kullanıcılar için bu tamamen farklı sonuçlar doğurabilir.

Brad Abrams, .NET framework’ü geliştirme aşamasının başlarında, String adında bir sınıfın içinde şu method yüklemelerin problem yarattığını söylüyor:

public class String
{
public int IndexOf (string value);
// Örnekteki değerin index'ini geri döndürür.
public int IndexOf (char value);
// Örnekteki değerin index'ini geri döndürür.
public int IndexOf (char[] value);
// Değerin içindeki karakterlerin ilk index'ini geri döndürür.
} 

Buradaki son method, farklı sonuçlara yol açtığını söylüyor. Şöyle ki;

 "Joshua, Hannah, Joseph".IndexOf("Hannah"); // Geriye 7 döndürür. 

Fakat

"Joshua, Hannah, Joseph".IndexOf(new char [] {'H','a','n','n','a,'h;");
 // Geriye 3 döndürür.

Buradaki son methodun isminin method aşırı yüklemesine bağlı kalınarak aşağıdaki şekilde olması gerektiğini söyler:

public int IndexOfAny (char [] value);

C#’ta Virtual, Override ve Abstract Methodlar

C#’ta bir method örneği, virtual anahtar sözcüğü ile tanımlanırsa, o methoda virtual (sanal) method adı verilir.

Bir sanal method, ana sınıf tipinden ziyade, güncel atanmış tip ile ilişkilendirilmiş methodu kullanmanıza izin verir.

Bir sanal method türetilmiş sınıfı tarafından etkisiz hale getirilebilir. Bir method örneğinde override anahtar sözcüğü varsa, o method, kalıtım alınmış sanal methodu aynı method imzası ile geçersiz kılar. Bu tür bir sanal method eğer overload olmuşsa, tanımlanmış değişkenin data tipinden ziyade verinin gerçek sınıf tipi runtime zamanında kullanılır. Bunun anlamı; temel sınıf bir çok türetilmiş sınıf tarafından kullanılabilir.

Önemli: Buradaki ince bir nokta, override edilmiş bir sanal method, hala o sınıfın bir methodu olarak hesab katılır. Türetilmiş sınıf, sanal sınıf override edildiği zaman onu göstermek zorundadır. Bu override anahtar sözcüğünü yeni method oluşumunda kullanılarak gösterilir.

Bir abstract (soyut) method, uygulanmayan bir sanal methodtur. Bu methodlar, abstract anahtar sözcüğü ile tanımlanır ve sadece astract olarak tanımlanmış sınıflara izin verilir. Bir soyut sınıf, soyut olmayan türetilmiş tüm sınıflar tarafından override edilmelidir.

Aşağıdaki örnekte; soyut sınıf olarak tanımlanmış Deyim sınıfı, ki bir deyim ifade ağacı düğümü temsil eder, 3 tane de türetilmiş sınıf, Sabit, DegiskenReferansi ve İslem, ki bunlar da sabitlerin, değişken referanslarının ve aritmetik işlemlerin deyim ifade ağaçlarını uygularlar.


using System;
using System.Collections;
using System.Linq;
using System.Text;

namespace HelloWorld
{
public abstract class Deyim
{
public abstract double Hesapla(Hashtable vars);
}
public class Sabit : Deyim
{
double value;
public Sabit(double value)
{
this.value = value;
}
public override double Hesapla(Hashtable vars)
{
return value;
}
}
public class DegiskenReferansi : Deyim
{
string name;
public DegiskenReferansi(string name)
{
this.name = name;
}
public override double Hesapla(Hashtable vars)
{
object value = vars[name];
if (value == null)
{
throw new Exception("Bilinmeyen deşiken " + name);
}
return Convert.ToDouble(value);
}
}
public class İslem : Deyim
{
Deyim sol;
char op;
Deyim sag;

public İslem(Deyim sol, char op, Deyim sag)
{
this.sol = sol;
this.op = op;
this.sag = sag;
}

public override double Hesapla(Hashtable vars)
{
double x = sol.Hesapla(vars);
double y = sag.Hesapla(vars);
switch (op)
{
case '+': return x + y;
case '-': return x - y;
case '*': return x * y;
case '/': return x / y;
}
throw new Exception("Bilinmeyen operatör");
}
}
} 

Bu 4 sınıf, modern matematik işlemler için kullanılabilir. Örneğin, bu sınıf örneklerini kullanarak x + 7 deyimi şu şekilde gösterilebilir;


static void Main()
{
Deyim d = new İslem(new DegiskenReferansi("x"), '+', new Sabit(7));
} 

Burada Deyim sınıfının Hesapla methodu verilen değeri hesaplamak ve bir dobule değeri üretmek görevindedir. Bu method Hashtable adında değişken isimlerini ve değerlerini içeren bir parametre alır. Hesapla methodu, sanal soyut bir method olduğundan, bunun anlamı; soyut olmayan türetilmiş sınıflar güncel bir uygulama sağlamak için bu methodu override etmek zorundalar.

Sabit sınıfının Hesapla implementasyonu, basit olarak geriye depolanmış bir sabit (constant) döndürür. DegiskenReferansi implementasyonu, Hashtable içerisindeki değişken ismine bakar ve sonuçlanan değeri geri döndürür. İslem implementasyonun görevi, öncelikle sol ve sağ operandlarını (Recursif olarak çağırılan Hesapla() methodları ile) hesaplayarak, verilen aritmetik işlemi gerçekleştirmektir.

Aşağıdaki program Deyim sınıfını kullanarak x * (y + 3) işlemini farklı değerler kullanarak hesaplar;


static void Main()
{
Deyim d = new İslem(new DegiskenReferansi("x"), '*', new İslem(new DegiskenReferansi("y"), '+', new Sabit(3)));

Hashtable vars = new Hashtable();

vars["x"] = 2;
vars["y"] = 5;
Console.WriteLine(d.Hesapla(vars)); // Çıktı 16 olur.

vars["x"] = 3;
vars["y"] = 7;
Console.WriteLine(d.Hesapla(vars)); // Çıktı 30 olur.
} 

C#’ta Method Parametreleri

Parametreler, bir değere atanan ya da bir methoda referans eden değişkenler için kullanılır. Method parametreleri, method çağırıldığında, asıl değerlerini argümanlardan alırlar. 4 çeşit parametre tipi bulunur; değer parametreleri (value parameters), referans parametreleri (reference parameters), çıktı parametreleri (output parameters) ve parametre dizileri (parameters arrays).

Değer parametreleri (value parameters), girdilerde parametre geçirilmelerinde kullanılır. Bir değer parametresi, methodlara geçirilen argümanların ilk değerlerini içeren yerel değişkenler ile uyuşur.

Değer parametrelerindeki değişiklikler, parametreye geçirilen argümanları etkilemezler.

Önemli: Değer parametrelerindeki değişiklik durumları, argümanları etkilemezler kelimeleri yanıltıcı olabilir çünkü türetilmiş sınıflar referans tip’te parametre içeriğini değiştirebilir. Parametre değerleri değiştiremez fakat referans edilmiş içerik (nesne) değiştirebilir.

Değer parametreleri seçimli olabilir, varsayılan değeri belirlemek için, böylece argümanlara ilişkilendirme yapılabilir.

Referans parametreleri, hem girdi (input) hem de çıktı (output) parametre geçişleri için kullanılır. Referans parametrelerini geçiş argümanları; bir değişken, yürütme süresinceki methodlar, ayrıca referans parametreleri argüman değişkenleri ile  aynı bellek bölgesini simgelerler. Bir referans parametresi ref anahtar sözcüğü ile gösterilir. Aşağıdaki örnek; ref anahtar sözcüğünün kullanımını gösterir.

class Test
{
static void Degistir(ref int x, ref int y)
{
int temp = x;
x =  y;
y = temp;
}
static void Main()
{
int i = 10, j = 20;
Degistir(ref i, ref j);
Console.WriteLine("{0} {1}", i, j); // Çıktı 20 10 olur.
}
}

Bu örneği ref anahtar sözcüksüz yazsaydık, çıktı “10 20” olurdu. Yani o değişkenlere referans vermeden bunların yerleri değiştirilemezdi.

Önemli: Referans parametreleri C# tarafından “referans ile geçiş” olarak adlandırılır; önce bir nesne örneğini bir methoda geçirir ve o method o nesne örneğine bir referans alır.

Referans parametreleri, çok küçük bir farkla “referans ile geçiş”’ten farklıdır. Bu durumda, referans bir değişkenin kendisindedir, bir nesne örneğinde değil. Eğer bu değişken, bir değer tipi içerirse bu tamamen normal bir durumdur. Bu değere “referans ile geçiş” yapılmamıştır değişken bu değeri tuttuğu sürece.

Referans parametrelerini düşünmenin iyi bir yolu, referans parametreleri, değişkenleri argümanlara geçiştirmek için bir takma ad’a dönüşürler şeklinde düşünmektir. Yukardaki örnekte, x ve i aslında aynı değişkendirler. Bellekte aynı bölgeye kaynak gösterirler.

Çıktı parametreleri (Output parameters), çıktı parametre geçişleri için kullanılırlar. Çıktı parametreleri referans parametrelerine benzerdir, fark olarak burada değeri ilk çağıran-sağlayan argüman önemsizdir. Çıktı parametreleri, out anahtar sözcüğü ile gösterilirler. Aşağıdaki örneği inceleyebiliriz;

using System;

namespace HelloWorld
{
class Test
{
static void Bolme(int x, int y, out int sonuc, out int kalan)
{
sonuc = x / y;
kalan = x % y;
}
static void Main()
{
int son, kal;
Bolme(20, 3, out son, out kal);
Console.WriteLine("{0} {1}", son, kal); // Çıktı 6 2 olur.
}
}
}

Önemli: CLR, direkt olarak sadece ref parametrelerini destekler. Out parametresi metadata içerisinde temsil edilir.

Parametre dizileri, bir methoda birden fazla sayıda argüman değişkeninin geçirilmesine izin verirler. Parametre dizileri, params anahtar sözcüğü ile gösterilirler. Bir methodun sadece son parametresi bir parametre dizisi olabilir ve parametre dizisinin tipi tek boyutlu dizi tipi olmak zorundadır. System.Console sınıfının Write ve Writeline methodları parametre dizilerinin kullanımına iyi bir örnektir. Bu iki method şu şekilde tanımlanmıştır:

 public class Console
{
public static void Write(string fmt, params object[] args) {...}
public static void WriteLine(string fmt, params object[] args) {...}
} 

Bu tür method tanımlamalarına, Visual Studio içerisinde methodun üzerine gelip sağ tıkladığımızda “Go to definition” sekmesiyle ulaşabiliriz. (Kısayol F12)

 

 

 

 

 

 

 

Parametre dizileri içeren bir method içerisinde, parametre dizileri bir dizi tipinin parametreleri ile tam olarak aynı şekilde davranır. Fakat, bir parametre dizisine sahip method, hem parametre dizisi tipindeki basit argümanı hem de parametre dizisindeki element tiplerinin argüman numaralarını geçirebilir. Sonrasında, bir dizi örneği otomatik yaratılır ve verilen argümanları ilişkilendirir. Örneğin;

 Console.WriteLine("x={0} y={1} z={2}", x, y, z); 

aşağıdaki koda eşdeğerdir

 string s = "x={0} y={1} z={2}";
object[] args = new object[3];
args[0] = x;
args[1] = y;
args[2] = z;
Console.WriteLine(s, args);

Önemli: Params anahtar sözcüğü kullanımının güzel bir tarafı da, opsiyonel bir kısayol oluşturmasıdır. Yani aşağıdaki şekilde bir kod yazmamızı önler:

 static object[] GetArgs() { ... }

static void Main()

{
object[ ] args = GetArgs();
object a = args[0];
object b = args[1];
object c = args[2];
Console.WriteLine("a={0} b={1} c={2}", a, b, c );
} 

Şimdi de bu methodu çağırıyorum ve compiler benim yerine bu parametreler için bir dizi oluşturuyor.

 static object[] GetArgs() { ... }

static void Main()

{
Console.WriteLine("a={0} b={1} c={2}", GetArgs() );
} 

Fakat bu günlerde, .NET içerisinde sadece çok az method bir dizi geriye döndürüyor. Bu nedenle bir çok yazılımcı, IEnumerable<T> kullanmayı esneklik amacıyla tercih ediyorlar. Bu nedenle ileride şöyle bir kod yazabilirsiniz;

 static IEnumerable<object> GetArgs { }

static void Main()
{
Console.WriteLine("x={0} y={1} z={2}", GetArgs().ToArray());
} 

C#’ta Methodlar

C#’ta methodlar, bir sınıf ya da nesne tarafından gerçekleştirilen hesaplamaları ya da eylemleri uygulayan üyelerdir. Static methodlara sınıflar aracılığıyla erişilebilirken, Instance (örnek) methodlara bir sınıfın örneği tarafından erişilebilir.

Methodlar bir parametre listesine (boş olabilen) sahip olabilir ki bunlar methoda geçirilen değer ya da değişkenlere referans gösterirler. Bununla birlikte bir geri dönüş tipine sahip olabilirler (return type) ki bu da method içinde hesaplanan değerlerin programa geri vereceği değeri belirler. Eğer bir methodun geri döüş tipi “void” ise, o method bir değer döndürmez.

Tıpkı tipler gibi, methodlar da, bir takım tip parametre setlerine sahip olabilirler. Bunun amacı method çağırıldığında, hangi tiplerin belirlenmesi gerektiğidir.

Bir method imzası (signature), sınıf içerisinde eşsiz bir değer olmalıdır. Bir method imzası; var olan methodun ismi, tip parametrelerin sayısı, erişim düzenleyicileri (modifier) ve parametrelerin tiplerinden oluşur. Method imzası geri dönüş tipi içermez.

Önemli: Generic tiplerin şanssız bir sonucu olarak, yapısal bir tip (constructed type), özdeş imzalar içeren iki farklı methoda sahip olabilir. Örneğin;


class Sınıf<T>
{
void Method(T t){}
void Method(int t){}
}

şeklide bir kod hiçir hata içermez. Fakat Sınıf<int>’in özdeş imzalara sahip iki farklı methodu olmuş olur. Daha sonra göreceğimiz gibi, bu durum method’ların aşırı yüklenmesinde ve arayüz implementasyonlarında bazı ilginç senaryolara yol açar. İyi bir yönlendirme olarak; bunu yapmayın.