Berk Akademi
Ana Sayfa
ÖZEL KODLAMA DERSLERİ
Yazılım Özel Ders
Tüm birebir programlara genel bakış
Python Yazılım Kursu
Sıfırdan ileri seviyeye birebir Python
Java Yazılım Kursu
OOP odaklı birebir Java eğitimi
AP Computer Science Principles
AP CSP sınav hazırlığı
GRUP DERSLERİ
Python & Django Masterclass
SINIRLI KONTENJAN
Java & Spring Boot Masterclass
SINIRLI KONTENJAN
C# .NET Masterclass
SINIRLI KONTENJAN
VİDEO DERSLER
Sıfırdan Temel Python Kursu
Kendi Hızında Öğren
ÜCRETSİZ
Seviye Testi
Ücretsiz — Python, Java, algoritma seviye testleri
Kariyerini Keşfet
Sertifika Doğrula
Belge numarası ve soyad ile doğrulama

C# SelectMany Kullanımı: Select ile Farkı ve Düzleştirme

csharp-selectmany-kullanimi-select-ile-farki
Bu yazıda neler var?
  1. SelectMany Ne İşe Yarar? Önce Veri Şeklini Görün
  2. Select İç İçe Koleksiyonlarda Neden İç İçe Sonuç Üretir?
  3. SelectMany ile İç Koleksiyonları Tek Listeye Düzleştirme
  4. Null ve Boş İç Liste Durumlarında Güvenli SelectMany Kullanımı
  5. Select mi SelectMany mi? Veri Tipini Okuyarak Karar Verin
  6. Sık Sorulan Sorular

C# SelectMany, iç içe koleksiyonları tek bir akışta birleştirmek için kullanılır. Select her elemanı başka bir değere dönüştürür; bu dönüşümün sonucu yine bir koleksiyonsa koleksiyon katmanını korur. SelectMany ise her elemanın ürettiği iç koleksiyonları bir araya getirerek daha düz bir sonuç üretir.

Bu farkı anlamanın en güvenilir yolu, yalnızca metot adına değil, giriş ve çıkış veri tiplerine bakmaktır. C# koleksiyon dönüşümleri konusunda seviyenizi kontrol etmek için C# bilgi testi üzerinden kısa bir değerlendirme yapabilirsiniz.

SelectMany Ne İşe Yarar? Önce Veri Şeklini Görün

Elinizde List<List<string>> varsa veri tek bir liste değildir; her elemanı kendi içinde başka bir string listesidir. Örneğin ders kategorilerini şu şekilde düşünebilirsiniz:

var categories = new List<List<string>>
{
    new() { "Değişkenler", "Döngüler" },
    new() { "Sınıflar", "Kalıtım" }
};

Bu verinin dış katmanı iki kategori listesinden oluşur. İç katmanlarda ise toplam dört ders adı bulunur. Select kullanıldığında her kategori listesi ayrı bir sonuç olarak kalır. SelectMany kullanıldığında ise bu iç listeler tek bir akışta birleşir ve sonuç şekli IEnumerable<string> olur.

Dolayısıyla temel mantık şudur: Girdiniz IEnumerable<IEnumerable<string>> gibi iç içe bir yapıysa ve hedefiniz tek tek string değerlerine ulaşmaksa, SelectMany uygun araçtır. Ancak her dış eleman için ayrı bir koleksiyon elde etmek istiyorsanız, iç katmanı koruyan Select davranışı daha doğrudur.

Select İç İçe Koleksiyonlarda Neden İç İçe Sonuç Üretir?

Select İç İçe Koleksiyonlarda Neden İç İçe Sonuç Üretir?

Select metodunun mantığı “koleksiyondaki her elemanı bir kez dönüştür” şeklindedir. Selector olarak verilen lambda ifadesinin girdisi dış koleksiyonun tek bir elemanıdır. Bu eleman bir listeyse ve lambda yine bu listeyi döndürüyorsa, Select her listeyi olduğu gibi sonuç akışına ekler.

var selected = categories.Select(category => category);
// Tip: IEnumerable<List<string>>

foreach (var category in selected)
{
    Console.WriteLine(string.Join(", ", category));
}

Buradaki lambda ifadesini adım adım okuyalım:

  • category değişkeninin tipi List<string> değerindedir.
  • => category, aldığı listeyi değiştirmeden geri döndürür.
  • Bu nedenle her sonuç elemanı bir string değil, bir List<string> olur.
  • Sonuç tipi de IEnumerable<List<string>> benzeri iç içe bir yapı haline gelir.

Aynı durum DTO listelerinde de görülür. Örneğin her kategorinin kendi kurslarını taşıdığı bir model düşünelim:

class Category
{
    public string Name { get; set; } = "";
    public List<string> Courses { get; set; } = new();
}

var categories = new List<Category>
{
    new() { Name = "C#", Courses = new() { "Değişkenler", "LINQ" } },
    new() { Name = "Java", Courses = new() { "Sınıflar", "Miras" } }
};

var coursesByCategory = categories.Select(category => category.Courses);
// IEnumerable<List<string>>

Burada Select dış koleksiyondaki kategori sayısını mantıksal olarak korur: her kategori için bir kurs listesi üretir. İç listelerin içeriğini otomatik olarak tek seviyeye indirmez.

Metot Lambda çıktısı Sonuç şekli
Select IEnumerable<string> IEnumerable<IEnumerable<string>>
SelectMany IEnumerable<string> IEnumerable<string>

Özetle Select, lambda ifadesinin döndürdüğü veri şeklini korur. Lambda bir koleksiyon döndürüyorsa sonuç da koleksiyonların koleksiyonu olur; düzleştirme davranışı kendiliğinden gerçekleşmez.

SelectMany ile İç Koleksiyonları Tek Listeye Düzleştirme

SelectMany ile İç Koleksiyonları Tek Listeye Düzleştirme

SelectMany, bir koleksiyondaki her elemanın içinden dönen IEnumerable<T> değerlerini tek bir akışta birleştirir. Bu nedenle List<List<string>> gibi iç içe bir yapı, düzleştirme sonrasında List<string> biçimine dönüştürülebilir. Lambda yazımında temel fark, Select(x => ...) ifadesinin her eleman için ayrı bir sonuç üretmesi; SelectMany(x => ...) ifadesinin ise bu sonuçları tek seviyede birleştirmesidir.

Metot Girdi Selector çıktısı Nihai veri şekli Tipik kullanım
Select List<List<string>> IEnumerable<string> içeren sonuçlar IEnumerable<IEnumerable<string>> Her iç koleksiyonu ayrı sonuç olarak korumak
SelectMany List<List<string>> IEnumerable<string> IEnumerable<string> Tüm iç koleksiyonları tek akışta birleştirmek

Aşağıdaki örnekte her dış liste elemanı bir ders kategorisini, içindeki metinler ise o kategorideki dersleri temsil eder. İkinci kategori boş, üçüncü kategori ise null olarak verilmiştir. ?? Enumerable.Empty<string>() ifadesi, null iç listeyi eleman içermeyen güvenli bir enumerable'a dönüştürür.

using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main()
    {
        List<List<string>> categories = new List<List<string>>
        {
            new List<string> { "Değişkenler", "Döngüler" },
            new List<string>(),
            null,
            new List<string> { "Sınıflar" }
        };

        List<string> courses = categories
            .SelectMany(category => category ?? Enumerable.Empty<string>())
            .ToList();

        Console.WriteLine(string.Join(", ", courses));
    }
}

Beklenen konsol çıktısı: Değişkenler, Döngüler, Sınıflar. Boş liste herhangi bir ders üretmeden akışın devam etmesini sağlar; null liste ise boş enumerable'a çevrildiği için aynı şekilde atlanır. Canlı sınıflı eğitimlerde bu tür veri dönüşümlerini eğitmen eşliğinde ve uygulama yaparak öğrenmek isteyenler, canlı sınıflı yazılım eğitimleri kapsamında benzer örnekleri inceleyebilir.

Null ve Boş İç Liste Durumlarında Güvenli SelectMany Kullanımı

Boş bir iç koleksiyon ile null bir iç koleksiyon aynı durum değildir. Boş koleksiyon geçerli bir nesnedir ve içinde eleman bulunmadığı için SelectMany sonucuna katkı yapmadan doğal biçimde atlanır. Null koleksiyon ise selector'ın beklediği enumerable değerini sağlayamaz; risk, düzleştirme sırasında iç koleksiyon üzerinde işlem yapılmak istendiğinde ortaya çıkar.

Bu nedenle null gelebilecek kaynaklarda System.Linq ad alanındaki Enumerable.Empty<T>() metodu savunmacı bir yaklaşım sunar:

var allCourses = categories
    .SelectMany(category =>
        category.Courses ?? Enumerable.Empty<Course>())
    .ToList();

Basit bir DTO senaryosunda Category sınıfı, IEnumerable<Course> Courses özelliğine sahip olabilir. Amaç, tüm kategorilerdeki dersleri tek akışta toplamaktır. category.Courses null ise onu boş enumerable'a çevirmek, hatalı bir değer üretmek yerine o kategorinin sonuçta ders katkısı yapmamasını sağlar.

Bu yaklaşım özellikle dış kaynaktan, dosyadan veya API yanıtından gelen kategori-ders verilerinde önemlidir. Verinin her kategoride mutlaka dolu olacağını varsaymak yerine, null ve boş koleksiyonları açıkça ele almak kodun davranışını daha öngörülebilir kılar.

Select mi SelectMany mi? Veri Tipini Okuyarak Karar Verin

Select ile SelectMany arasındaki doğru tercihi yapmak için önce hedef veri tipine bakın. Her kaynak elemanı tek bir değer üretiyorsa sonuç düz bir koleksiyon olur; her kaynak elemanı başka bir koleksiyon üretiyorsa Select iç içe yapı oluşturur, SelectMany ise bu katmanları birleştirir.

  1. Her eleman tek bir değer üretiyorsa Select kullanın. Örneğin her öğrencinin yalnızca adını almak, IEnumerable değerini IEnumerable<string> değerine dönüştürür.
  2. Her eleman bir koleksiyon üretiyorsa önce sonuç tipini kontrol edin. kategoriler.Select(kategori => kategori.Dersler) ifadesi, IEnumerable<IEnumerable<string>> üretir.
  3. Hedefiniz IEnumerable<IEnumerable<X>> gibi katmanlı bir yapıysa, bu yapıyı korumak istediğiniz için Select doğru tercih olabilir.
  4. Hedefiniz IEnumerable<X> ise, SelectMany kullanarak iç koleksiyonların düzleştirildiğini doğrulayın.
  5. İç koleksiyonun null olma ihtimali varsa ?? Enumerable.Empty<X>() ile güvenli bir varsayılan koleksiyon sağlayın.
İfade Her kaynak elemanının ürettiği değer Sonuç tipi
Select(x => x.Items) Bir koleksiyon IEnumerable<IEnumerable<string>>
SelectMany(x => x.Items) Bir koleksiyonun elemanları IEnumerable<string>

Örneğin CourseCategory adlı bir DTO içinde List<string> CourseNames alanı bulunduğunu düşünün. Kategorileri ekranda kategori bazında göstermek istiyorsanız Select kullanarak her kategoriye ait ders listesini koruyabilirsiniz. Arama kutusunda tüm ders adlarını tek bir akışta filtrelemek istiyorsanız SelectMany daha uygundur. Buradaki karar, hangi metodun “daha iyi” olduğundan çok, çıktıdaki veri katmanını korumak mı yoksa kaldırmak mı istediğinizle ilgilidir.

Her durumda SelectMany kullanmak doğru değildir. İç içe gruplama, kategori bilgisi veya hiyerarşik yapı daha sonra kullanılacaksa Select ile katmanları koruyun. C# öğrenimini video formatında, örnekleri tekrar izleyerek sürdürmek isteyenler asenkron C# ve programlama video eğitimlerini inceleyebilir.

Sık Sorulan Sorular

SelectMany ile Select arasındaki temel veri tipi farkı nedir?

Select, her kaynak elemanı için bir sonuç üretir. Sonuçların kendisi koleksiyonsa çıktı IEnumerable<IEnumerable<T>> gibi iç içe bir yapı olur. SelectMany ise bu iç koleksiyonların elemanlarını tek akışta birleştirerek IEnumerable<T> üretir.

SelectMany null veya boş bir iç listeyle karşılaşırsa ne olur?

Boş bir iç liste düzleştirme sonucuna hiç eleman eklemez. Ancak selector null döndürürse işlem güvenli değildir ve çalışma sırasında hata oluşabilir. Bu ihtimali önlemek için items ?? Enumerable.Empty<T>() yaklaşımı kullanılmalıdır.

Bir koleksiyonda Select mi yoksa SelectMany mi kullanmam gerektiğini nasıl anlarım?

Önce her kaynak elemanının tek değer mi, yoksa başka bir koleksiyon mu ürettiğine bakın. İç içe yapıyı koruyacaksanız Select, tüm alt elemanları tek akışta kullanacaksanız SelectMany seçin.

SelectMany kullanmadan iç içe listeleri düzleştirmek mümkün müdür?

Evet. İç içe listeler klasik foreach döngüleriyle gezilerek ayrı bir listeye eklenebilir. SelectMany, bu işlemi daha kısa ve fonksiyonel bir LINQ ifadesiyle yazmayı sağlar; zorunlu değil, pratik bir tercihtir.

Sonuç olarak doğru metodu seçmenin en güvenilir yolu, yazdığınız ifadenin ürettiği veri tipini ve sonraki işlemde ihtiyaç duyduğunuz veri şeklini birlikte değerlendirmektir.

Bu içerik aradığın cevabı verdi mi?
Yanıtın, hangi yazıları geliştirmemiz gerektiğini anlamamıza yardımcı olur.
Bu içeriğin üretilmesinde yapay zeka araçlarından destek alınmıştır.

Bu konudan sonra ne okuyabilirsin?

Tüm yazılar

İlgili Eğitimler

Berk Keskin — Yazılım Geliştirici ve Eğitmen
Yazar

Berk Keskin Kimdir?

Yazılıma 12 yaşında başladı; bugün öğrencinin seviyesine ve hedefine göre şekillenen sürdürülebilir öğrenme sistemleri tasarlıyor. 500'den fazla kişiye ezber değil, düşünerek kod yazmayı öğretti — Berk Akademi'de izlemeye değil üretmeye dayalı öğrenme kültürünü o kuruyor.

WhatsApp Hemen Ara