C# LINQ kullanımı

C# ile uygulama geliştirirken günümüzün büyük bir kısmı listelerle, dizilerle veya veritabanından gelen koleksiyonlarla (List<T>) boğuşarak geçer. Veriyi çek, içinden aktif olanları bul, fiyata göre sırala, sadece isimleri alıp DataGridView’e bas…

Peki bu işlemleri yaparken hala sayfa sayfa foreach döngüleri, içi içe geçmiş if blokları mı yazıyorsunuz? Eğer öyleyse, C#’ın en büyük nimetlerinden biri olan LINQ (Language Integrated Query) ile tanışma (veya onu derinlemesine öğrenme) vaktiniz gelmiş demektir.

Bu rehberde, amele usulü kod yazmayı bırakıp, LINQ ile nasıl “Senior” seviyesinde temiz, okunabilir ve performanslı kod yazacağınızı adım adım inceleyeceğiz.

1. Sorun Nedir? (Geleneksel “Amele” Yöntemi)

Diyelim ki elimizde bir Urun listesi var. Sadece kategorisi “Elektronik” olan ve fiyatı 5000 TL’den büyük olan ürünleri bulup yeni bir listeye almak istiyoruz. Geleneksel yöntemle kodumuz şuna benzer:

List<Urun> filtrelenmisUrunler = new List<Urun>();

foreach (var urun in urunListesi)
{
    if (urun.Kategori == "Elektronik" && urun.Fiyat > 5000)
    {
        filtrelenmisUrunler.Add(urun);
    }
}

Bu kod sorunsuz çalışır. Ancak projeler büyüdükçe, bu tarz bloklar her yeri kaplamaya başlar. Okuması yorucudur, satır kalabalığı yapar ve hata yapmaya (bug) çok müsaittir.

Aynı kodu LINQ ile (Lambda Expressions kullanarak) şu şekilde yazarız:

using System.Linq; // Sayfanın en üstüne eklemeyi unutmayın!

var filtrelenmisUrunler = urunListesi
    .Where(u => u.Kategori == "Elektronik" && u.Fiyat > 5000)
    .ToList();

Sadece tek satır! Şimdi gelin, hayat kurtaran diğer LINQ metotlarına derinlemesine bakalım.

2. En Çok Kullanılan LINQ Metotları ve Gerçek Hayat Senaryoları

(Not: Aşağıdaki örneklerde urunListesi adında bir List<Urun> koleksiyonumuz olduğunu varsayıyoruz.)

A. Veri Filtreleme: Where

Koleksiyon içinde belirli bir şarta uyan elemanları getirmek için kullanılır.

// Sadece stokta olan ürünleri getir
var stoktakiUrunler = urunListesi.Where(u => u.StokAdedi > 0).ToList();

B. Tek Bir Eleman Bulmak: First, FirstOrDefault, SingleOrDefault

En çok karıştırılan ve mülakatlarda en sık sorulan 3’lü budur. Diyelim ki ID’si 15 olan ürünü arıyoruz:

  • First(): Aranan şarta uyan İLK kaydı getirir. Eğer şartı sağlayan hiçbir kayıt yoksa uygulama patlar (Exception fırlatır).
  • FirstOrDefault(): Aranan şarta uyan İLK kaydı getirir. Eğer kayıt bulamazsa exception fırlatmaz, null döner. Genelde en güvenli ve sık kullanılan yöntem budur.
    var arananUrun = urunListesi.FirstOrDefault(u => u.Id == 15); if(arananUrun != null) { /* İşlemler */ }
  • SingleOrDefault(): Aranan şarta uyan kaydı getirir. Ancak FirstOrDefault‘tan kritik bir farkı vardır: Eğer şarta uyan birden fazla kayıt bulursa hata fırlatır. Kayıt tek (unique) olmak zorundaysa (örneğin TC Kimlik No ile arama yapıyorsanız) bunu kullanmalısınız.

C. Sadece Belirli Sütunları Seçmek (Veri Dönüştürme): Select

Veritabanından 50 kolonluk koca bir tabloyu çektiniz ama DataGridView’e veya bir API yanıtına sadece ürün isimlerini dönmek istiyorsunuz. Tüm objeyi taşımak yerine Select kullanın:

// Sadece ürün isimlerinden oluşan yeni bir List<string> elde ederiz
List<string> urunIsimleri = urunListesi.Select(u => u.UrunAdi).ToList();

// Anonim tip (Anonymous Type) ile birden fazla alan seçmek:
var kisaListe = urunListesi.Select(u => new { u.Id, u.UrunAdi }).ToList();

D. Sıralama İşlemleri: OrderBy ve ThenBy

Manuel sıralama algoritmaları yazmaya son.

C#

// Fiyata göre ucuzdan pahalıya sırala
var ucuzdanPahaliya = urunListesi.OrderBy(u => u.Fiyat).ToList();

// Fiyata göre pahalıdan ucuza sırala, fiyatı aynı olanları isme göre A'dan Z'ye sırala
var siraliListe = urunListesi
    .OrderByDescending(u => u.Fiyat)
    .ThenBy(u => u.UrunAdi)
    .ToList();

E. Var mı / Yok mu Kontrolü (Performans Tüyosu): Any

Bir listede belirli bir şarta uyan eleman var mı diye kontrol etmek istiyorsunuz. Çoğu geliştirici şu hatayı yapar:

// YANLIŞ VE YAVAŞ: Tüm listeyi sayar, sonra 0'dan büyük mü diye bakar.
if (urunListesi.Where(u => u.Fiyat > 10000).Count() > 0) 

// DOĞRU VE HIZLI: Şarta uyan İLK elemanı bulduğu an aramayı bırakır ve True döner.
if (urunListesi.Any(u => u.Fiyat > 10000)) 
{
    Console.WriteLine("Listede 10.000 TL'den pahalı ürün var!");
}

F. Gruplama: GroupBy

Özellikle raporlama ekranlarında veya dashboard’larda hayat kurtarır. Ürünleri kategorilerine göre gruplayalım:

C#

var kategoriGruplari = urunListesi.GroupBy(u => u.Kategori);

foreach (var grup in kategoriGruplari)
{
    Console.WriteLine($"Kategori: {grup.Key} - Ürün Sayısı: {grup.Count()}");
}

3. İleri Seviye (Bonus) Bilgi: Deferred Execution (Ertelenmiş Çalışma) Nedir?

Bir LINQ sorgusu yazdığınızda (örneğin .Where veya .Select), o sorgu hemen çalıştırılmaz. Sadece bellekte bir “sorgu planı” olarak bekler. Sorgunun gerçek veriler üzerinde çalışıp sonuç üretmesi için .ToList(), .ToArray(), .Count(), .First() gibi işlemleri çağırmanız veya bir foreach döngüsüne sokmanız gerekir.

Buna Deferred Execution (Ertelenmiş Çalışma) denir. Bu sayede, Entity Framework kullanırken yazdığınız uzun LINQ sorguları veritabanına anında gitmez, siz veriyi gerçekten talep ettiğinizde tek ve optimize edilmiş bir SQL sorgusuna dönüşerek çalışır.

Özetle;

Eğer kodunuzda bir listenin içinde arama, filtreleme veya sıralama yapmak için for / foreach döngüsü açıyorsanız, ellerinizi klavyeden çekin ve “Bunu LINQ ile tek satırda nasıl yazarım?” diye düşünün. LINQ sadece kodunuzu kısaltmaz, aynı zamanda niyetinizi çok daha okunabilir hale getirir.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir