Metot, girdiler (parametreler) alan, işini yapan ve bir sonuç (dönüş değeri) verebilen adlandırılmış bir kod bloğudur. C#'ta her metot bir tipin içinde yaşar; bağımsız fonksiyonlar yoktur.
Çıktı:
Headphones 48.00
Cable 11.40
Bir Metodun Anatomisi
public static decimal PriceWithTax(decimal net, decimal taxRate)
{
return net * (1 + taxRate);
}
- Erişim belirleyici (
public,private, ...): onu kimin çağırabileceği. Yazılmazsa metot tipineprivate'tır. static: metot bir nesneye değil tipe aittir. Aşağıda daha fazlası var.- Dönüş tipi: döndürdüğü değerin tipi ya da hiçbir şey döndürmüyorsa
void. - Ad: geleneksel olarak PascalCase, genellikle bir fiil (
Calculate,SendEmail,TryParse). - Parametre listesi: sıfır ya da daha fazla
type nameçifti. Her parametre, çağıranın argümanından başlatılan yerel bir değişkendir. - Gövde: süslü parantezler arasındaki ifadeler.
Ad artı parametre tipleri (ve varsa ref, out ya da in belirleyicileri) metodun imzasını oluşturur. Dönüş tipi bunun parçası değildir; bu, overloading için önemlidir.
Dönüş Değerleri ve void
return metodu hemen bitirir ve bir değer geri verir. Dönüş tipi olan bir metot, içinden geçen her yolda o tipte bir değer döndürmelidir:
static string Grade(int score)
{
if (score >= 50)
return "pass";
} // error CS0161: 'Program.Grade(int)': not all code paths return a value
Derleyici her dalı kontrol eder. Eksik return "fail";'i ekleyin ya da o noktaya ulaşmak bir hataysa bir throw ekleyin.
Bir void metot hiçbir şey döndürmez. Yine de erken çıkmak için çıplak bir return; kullanabilir:
Çıktı:
ana@mail.com: newsletter sent
ben@mail.com: not subscribed, skipped
False
True
Expression-Bodied Metotlar
Bir metodun gövdesi tek bir ifadeyse => süslü parantezlerin ve return'ün yerini alır:
static decimal Discount(decimal price) => price * 0.1m;
static bool IsAdult(int age) => age >= 18;
static void Log(string message) => Console.WriteLine($"[log] {message}");
Bu aynı metodun daha kısa yazılmışıdır. Gövde tek bir ifade (bir çağrı, bir atama) olduğu sürece void metotlar için de çalışır.
Parametreler Kopyadır
Argümanlar varsayılan olarak değerle geçirilir: parametre argümanın bir kopyasını alır. Metodun içinde parametreye atama yapmak çağıranın değişkenini etkilemez:
Çıktı:
inside: 42
after: 21
scores: 70, 85, 100
List değişti, çünkü bir referans tipi için kopyalanan değer referanstır: metot ve çağıran aynı liste nesnesini gösterir. Metodun içinde scores = new List<int>() ile yeniden atama yapmak çağıranı etkilemezdi. Bir metodun çağıranın değişkenine atama yapmasına izin vermek için ref ya da out kullanın; parametrelere varsayılan değer vermek ve onları adıyla çağırmak için isteğe bağlı parametreleri ve adlandırılmış argümanları kullanın.
Bir Tuple ile Birkaç Değer Döndürmek
C# 7.0'dan beri bir metot adlandırılmış elemanları olan bir tuple döndürebilir ve çağıran onu ayrı değişkenlere ayrıştırabilir:
Çıktı:
min 15, max 27, avg 21.0
range 12
_ ihtiyacınız olmayan elemanı atar. Birçok yerde kullanılan sonuçlar için adlandırılmış property'leri olan küçük bir sınıf ya da record, şekli bir tuple'dan daha iyi belgeler.
Overloading
Parametre listeleri sayı, tip ya da tiplerin sırası bakımından farklıysa birkaç metot aynı adı paylaşabilir. Derleyici her çağrı için en iyi eşleşmeyi seçer:
Çıktı:
12.57
13.50
25
Area(5) tam eşleşme olduğu için int sürümünü seçer; Area(2.0) double olanı seçer. Metotlar yalnızca dönüş tipinde farklılaşamaz: int ve double döndüren iki Area(int) metodu CS0111 hatasıdır, Type 'Program' already defines a member called 'Area' with the same parameter types, çünkü Area(5) gibi bir çağrı onları ayırt edemezdi.
Hiçbir overload'un kabul etmediği bir çağrı da derleme zamanında başarısız olur: Area(1, 2, 3) CS1501, No overload for method 'Area' takes 3 arguments, Area("big") ise CS1503, Argument 1: cannot convert from 'string' to 'double' hatasıdır.
params: Değişken Sayıda Argüman
Bir params dizi parametresi hiç argüman dahil herhangi sayıda argüman kabul eder. Derleyici diziyi sizin için oluşturur:
Çıktı:
empty cart: 0 item(s), 0
one item: 1 item(s), 9.99
three items: 3 item(s), 19.75
from array: 2 item(s), 50
Kurallar: params son parametre olmalıdır (aksi halde CS0231), bir metotta en fazla bir tane olur ve mevcut bir diziyi geçirmek o diziyi olduğu gibi teslim eder. Console.WriteLine("{0} and {1}", a, b) ve string.Format params object[] metotlarıdır. C# 13 params'ı List<T> ve ReadOnlySpan<T> gibi diğer koleksiyon tiplerine genişletti; ondan önce yalnızca dizilere izin veriliyordu.
Statik ve Örnek Metotlar
Bir static metot tipe aittir ve tip adı üzerinden çağrılır: Math.Max(3, 7), Program.Total(...). Bir örnek metodu ise bir nesneye aittir ve o nesnenin alanlarını kullanabilir:
Çıktı:
12
Statik bir metottan nesne olmadan bir örnek metodu çağırmak C#'taki en yaygın başlangıç hatasıdır:
class Program
{
void Greet() => Console.WriteLine("hi");
static void Main()
{
Greet();
// error CS0120: An object reference is required for the non-static field, method, or property 'Program.Greet()'
}
}
Greet'i static işaretleyin ya da bir nesne oluşturup onun üzerinden çağırın: new Program().Greet();. static sayfası statik üyeleri ve statik sınıfları daha ayrıntılı ele alır.
Main Metodu
Main bir programın başladığı yerdir. static olmalıdır ve şu imzalar geçerlidir:
static void Main() { }
static void Main(string[] args) { } // command-line arguments
static int Main(string[] args) { return 0; } // exit code for the shell
static async Task Main() { } // C# 7.1 and later
async Task Main biçimi giriş noktasının doğrudan await etmesini sağlar (bkz. async ve await). C# 9'dan beri bir dosya bunun yerine top-level statements içerebilir: yeni bir dotnet new console projesinde olduğu gibi hiç sınıf ya da Main olmadan kod. Derleyici sınıfı ve Main metodunu onun etrafında üretir, yani aynı şeyin kısa yazılmışıdır; args yine kullanılabilir.
Özyineleme
Bir metot kendini çağırabilir. Her çağrı kendi parametrelerini ve yerel değişkenlerini alır ve bir temel durum zinciri durdurmalıdır:
Çıktı:
120
2432902008176640000
35
Temel durum olmadan ya da çok derin bir girdiyle her çağrı bir stack çerçevesi ekler ve program sonunda StackOverflowException ile ölür. Bu istisna yakalanamaz, bu yüzden derinliği bilinmeyen girdiler için özyinelemeyi bir döngü olarak yeniden yazın.
Yerel Fonksiyonlar
C# 7.0 yerel fonksiyonları getirdi: başka bir metodun içinde bildirilen ve yalnızca orada görünen metotlar. Çevreleyen metodun değişkenlerini kullanabilirler:
// C# 7.0 and later
static int CountValid(string[] codes)
{
int count = 0;
foreach (string code in codes)
{
if (IsValid(code)) count++;
}
return count;
bool IsValid(string c) => c.Length == 6 && char.IsLetter(c[0]);
}
Bir yardımcıyı, sınıfın geri kalanına açmadan tek çağıranının yanında tutarlar. C# 8'den beri dış değişkenleri yakalamayı yasaklamak için static işaretlenebilirler. Yerel fonksiyonun kullanılamadığı yerde, bu sayfadaki diğer örneklerde olduğu gibi aynı sınıftaki private statik bir metot aynı işi görür.
Sıkça Sorulan Sorular
C#'ta metot ile fonksiyon arasındaki fark nedir?
C#'ta her fonksiyon bir class, struct ya da record içinde bildirilir ve metot olarak adlandırılır. Bağımsız fonksiyonlar yoktur. Top-level statements (C# 9) ve yerel fonksiyonlar (C# 7) bile üretilmiş ya da çevreleyen bir tipin metotlarına derlenir. "Fonksiyon" gayriresmî olarak ve lambda'lar ile delegeler için kullanılır.
C#'ta params ne işe yarar?
params bir metodun tek tipte değişken sayıda argüman almasını sağlar: static int Sum(params int[] numbers) Sum(), Sum(4), Sum(4, 5, 6) ya da Sum(existingArray) olarak çağrılabilir. Derleyici argümanları bir diziye paketler. params parametresi sonuncu olmalıdır ve bir metotta yalnızca bir tane olabilir.
C#'ta Main metodu nedir?
Main programın giriş noktasıdır: çalışma zamanının ilk çağırdığı metot. static olmalıdır, void ya da int (çıkış kodu) döndürebilir ve komut satırı argümanları için string[] args alabilir. C# 7.1'den beri async Task Main de olabilir, C# 9'dan beri ise top-level statements derleyicinin onu sizin için üretmesini sağlar.
Bir C# metodundan birden fazla değer nasıl döndürülür?
Bir tuple döndürün: static (int Min, int Max) Range(int[] values) ve return (min, max);. Çağıran result.Min'i okuyabilir ya da var (lo, hi) = Range(values); ile ayrıştırabilir. Kodunuzda birlikte dolaşan değerler için küçük bir sınıf ya da record daha anlaşılırdır; out parametreleri daha eski bir alternatiftir.
Neden "An object reference is required for the non-static field, method, or property" hatası alıyorum?
Main gibi static bir metot bir örnek metodunu doğrudan çağırdı. Statik metotlar tipe aittir ve onu çağıracakları bir nesneleri yoktur. Ya çağrılan metodu static işaretleyin ya da önce bir nesne oluşturun: var app = new Program(); app.Greet();.
"not all code paths return a value" ne demek?
CS0161 hatası: dönüş tipi olan bir metodun return olmadan kapanış süslü parantezine ulaşan en az bir yolu var. Genellikle bir if değer döndürür ama ondan sonra bir else ya da son bir return yoktur. Metodun sonuna bir return (ya da throw) ekleyin.