LINQ Nedir?

Can Yüksel

Erdoğancan Yüksel

11 dakika 40 saniye okuma süresi

LINQ (Language Integrated Query) verilerin sorgulanması ve filtrelenmesi için C# ve diğer .NET dillerinde kullanılan bir teknolojidir. C# 3.0 ve .NET Framework 3.5 sürümü ile birlikte kullanılmaya başlanmıştır.

linq-nedir

LINQ Nedir?

LINQ(Language Integrated Query — Dil ile Tümleşik Sorgu), verilerin sorgulanması ve filtrelenmesi için C# ve diğer .NET dillerinde kullanılan bir teknolojidir. LINQ veri kaynakları üzerinde sorgular oluşturarak veriler üzerinde filtreleme, sıralama, gruplama gibi işlemlerin yapılmasını, verilerin birleştirilmesini ve verilerin dönüştürülmesini sağlayarak dil ile veri kaynakları arasında köprü kurmaktadır. C# 3.0 ve .NET Framework 3.5 sürümleri ile birlikte kullanılmaya başlanan LINQ hem küçük hem de büyük ölçekli projelerde kullanılabilmektedir.

LINQ kullanarak veri sorgulamalarını daha anlamlı ve okunabilir hale getirmek mümkündür.

LINQ'nun bazı uygulama alanları şunlardır:

  • LINQ to Objects: Bellek içindeki nesne koleksiyonları üzerinde çalışmayı ve sorgu yazılmasını sağlamaktadır. (List, Array, IEnumerable ve IQueryable gibi.) Kodun okunabilirliğinin arttırılması açısından fayda sağlamaktadır.

    Kod örneği:

    List<int> numbers = new List<int> {1,2,3,4,5,6,7,8,9,10};
    
    var evenNumbers = from number in numbers
                      where number % 2 == 0
                      select number;
    
    var oddNumbers = from number in numbers
                     where number % 2 == 1
                     select number;
    
    Console.WriteLine($"Even numbers:");
    foreach (var number in evenNumbers)
    {
        Console.WriteLine(number);
    }
    
    Console.WriteLine($"Odd numbers:");
    foreach (var number in oddNumbers)
    {
        Console.WriteLine(number);
    }
    
    //# Output:
     Even numbers:
     2
     4
     6
     8
     10
     Odd numbers:
     1
     3
     5
     7
     9
  • LINQ to SQL: Microsoft SQL Server veritabanı üzerinde sorgular çalıştırmamızı sağlamaktadır. Veritabanı tablolarını nesneye dayalı hale getirerek SQL sorgularının C# gibi .NET dilinde yazılmasına ve doğrudan veritabanına erişim sağlanmasına imkan tanımaktadır.

    Kod örneği:

    using (var db = new DataContext(connectionString))
    {
        var query = from customer in db.GetTable<Customer>()
                    where customer.City == "Istanbul"
                    select customer;
    
        foreach (var customer in query)
        {
            Console.WriteLine(customer.Name);
        }
    }
    
    //# Output:
     Ahmet
     Baran
     Can
     Ozan
     Dilek
     Şule
  • LINQ to Entities: Entity Framework veya Entity Framework Core ile entegre olarak çalışarak veritabanı tablolarının C# nesneleri ile eşleşmesini ve nesneye dayalı programlama yöntemiyle veritabanı yöntemlerinin gerçekleştirilmesini sağlamaktadır.

    Kod örneği:

    using (var ctx = new SchoolDBEntities())
    {    
        var student = (from s in ctx.Students
                    where s.StudentName == "Can"
                    select s).FirstOrDefault<Student>();
    
        Console.WriteLine($"{student.FirstName} {student.LastName}");
    }
    
    //# Output:
     Can Yüksel
  • LINQ to XML: XML verileri üzerinde sorgulama yapılması, verilerin dönüştürülmesi ve işlenmesi gibi işlemler için kullanılmaktadır. Bu şekilde XML veri kaynakları daha anlaşılır ve esnek hale gelmektedir.

    Kod örneği:

    XElement books = new XElement("Kitaplar",
        new XElement("Kitap",
            new XElement("Ad", "Suç ve Ceza"),
            new XElement("Yazar", "Fyodor Dostoyevski"),
            new XElement("Yil", 1866)),
        new XElement("Kitap",
            new XElement("Ad", "1984"),
            new XElement("Yazar", "George Orwell"),
            new XElement("Yil", 1949))
    );
    
    var query = from book in books.Elements("Kitap")
                where (int)book.Element("Yil") > 1900
                select new
                {
                    KitapAdi = book.Element("Ad").Value,
                    Yazari = book.Element("Yazar").Value
                };
    
    foreach (var book in query)
    {
        Console.WriteLine($"{book.KitapAdi} - {book.Yazari}");
    }
    
    //# Output:
     1984 - George Orwell
  • LINQ to DataSet: ADO.NET veri setleri(DataSet) üzerinde sorgulama yapmayı sağlamaktadır. DataSet' veritabanı sonuçlarının bellek içindeki bir kopyasıdır ve ilgili veriler üzerinde LINQ sorguları yazılabilmektedir. LINQ bu konuda esneklik sağlamaktadır.

    Kod örneği:

    // DataSet ve DataTable oluşturma
    DataSet ds = new DataSet();
    DataTable dt = new DataTable("Workers");
    
    dt.Columns.Add("Id", typeof(int));
    dt.Columns.Add("FirstName", typeof(string));
    dt.Columns.Add("LastName", typeof(string));
    dt.Columns.Add("Department", typeof(string));
    
    // Veri ekleme
    dt.Rows.Add(1, "Ahmet", "Yılmaz", "IT");
    dt.Rows.Add(2, "Naz", "Kara", "İK");
    dt.Rows.Add(3, "Can", "Yüksel", "IT");
    dt.Rows.Add(4, "Mehmet", "Şahin", "Muhasebe");
    
    ds.Tables.Add(dt);
    
    // LINQ sorgusu
    var sorgu = from calisan in ds.Tables["Workers"].AsEnumerable()
                where calisan.Field<string>("Department") == "IT"
                select new
                {
                    FullName = calisan.Field<string>("FirstName") + " " + calisan.Field<string>("LastName"),
                    Department = calisan.Field<string>("Department")
                };
    
    foreach (var calisan in sorgu)
    {
        Console.WriteLine($"{calisan.FullName} - {calisan.Department}");
    }
    
    //# Output:
     Ahmet Yılmaz - IT
     Can Yüksel - IT

LINQ Operatörleri

1.Filtering (Filtreleme)

Filtreleme operatörleri veri koleksiyonları üzerinde belirlenen kriterler doğrultusunda elemanları seçerek filtrelemeye olanak tanımaktadır. LINQ'da filtreleme işlemleri için Where ve OfType operatörleri yaygın olarak kullanılmaktadır.

Where operatörü belirli bir koşulu sağlayan öğeleri filtrelemek ve seçmek için kullanılmaktadır. Koşullar lambda ifadeleri ile belirtilmektedir.

OfType operatörü koleksiyondaki belirli bir türdeki öğeleri filtrelemek ve seçmek için kullanılmaktadır. Özellikle birden fazla türde veri içeren koleksiyonlar için kullanışlıdır.

Where operatörü kullanımı için kod örneği:

record Student(string Name, int Point) { }

List<Student> students = new List<Student>() {
    new Student("Ahmet", 38),
    new Student("Gülsu", 78),
    new Student("Can", 55),
    new Student("Barış", 86),
    new Student("Haktan", 48),
    new Student("Deniz", 62),
    new Student("Selin", 22),
    new Student("Özlem", 92),
    new Student("Emre", 90),
    new Student("Ezgi", 42),
};

var successfulStudents = students.Where(s => s.Point >= 45).Select(x => x.Name).ToList();
var failedStudents = students.Where(s => s.Point < 45).Select(x => x.Name).ToList();

Console.WriteLine("Passed students list:");
foreach (var student in successfulStudents)
{
    Console.WriteLine(student);
}

Console.WriteLine("Failed students list:");
foreach (var student in failedStudents)
{
    Console.WriteLine(student);
}

//# Output:
Passed students list:
 Gülsu
 Can
 Barış
 Haktan
 Deniz
 Özlem
 Emre
Failed students list:
 Ahmet
 Selin
 Ezgi

OfType operatörü kullanımı için kod örneği:

List<object> mixedList = new List<object> { 1, 2, 3, "Ahmet", "Mehmet", "Ankara", 88, 100, "İstanbul", true, false, 55.3m, 88.8m, false };

var stringElements = mixedList.OfType<string>().ToArray();
var booleanElements = mixedList.OfType<bool>().ToArray();
var intElements = mixedList.OfType<int>().ToArray();
var decimalElements = mixedList.OfType<decimal>().ToArray();

Console.WriteLine("String elements:");
foreach(var element in stringElements)
{
    Console.WriteLine(element);
}

Console.WriteLine("Boolean elements:");
foreach (var element in booleanElements)
{
    Console.WriteLine(element);
}

Console.WriteLine("Integer elements:");
foreach (var element in intElements)
{
    Console.WriteLine(element);
}

Console.WriteLine("Decimal elements:");
foreach (var element in decimalElements)
{
    Console.WriteLine(element);
}

// Output:
// String elements:
// Ahmet
// Mehmet
// Ankara
// İstanbul
// Boolean elements:
// True
// False
// False
// Integer elements:
// 1
// 2
// 3
// 88
// 100
// Decimal elements:
// 55,3
// 88,8

2.Projection (Yansıtma)

Yansıtma operatörleri veri koleksiyonundaki verileri farklı formlara dönüştürerek yeni bir sonuç veri seti oluşturmaktadır. LINQ'da yansıtma işlemleri için Select ve SelectMany operatörleri yaygın olarak kullanılmaktadır.

Select operatörü genellikle koleksiyondaki bir alanı seçip yeni bir forma dönüştürmek için kullanılmaktadır.

SelectMany operatörü koleksiyonun her bir öğesini bir IEnumerable koleksiyonuna çıkarır ve bunları düz bir liste haline getirir. Çok seviyeli veri yapılarını düzleştirmek için kullanılmaktadır.

Select operatörü kullanımı için kod örneği:

record People(string Name, int Age, Gender Gender ) { }

enum Gender
{
    Female,
    Male
}

List<People> peoples = new List<People>();

peoples.Add(new People("Can", 30, Gender.Male));
peoples.Add(new People("Zeynep", 24, Gender.Female));
peoples.Add(new People("Emre", 18, Gender.Male));
peoples.Add(new People("Barış", 30, Gender.Male));
peoples.Add(new People("Haktan", 30, Gender.Male));
peoples.Add(new People("Melisa", 35, Gender.Male));

List<string> personNames =  peoples.Select(x => x.Name).ToList();

Console.WriteLine("Name list:");
foreach(string personName in personNames)
{
    Console.WriteLine(personName);
}

//# Output:
Name list:
Can
Zeynep
Emre
Barış
Haktan
Melisa

SelectMany operatörü kullanımı için kod örneği:

record Student(string Name, int Age, Gender Gender, IEnumerable<string> Lessons) { }

enum Gender
{
    Female,
    Male
}

List<Student> students = new List<Student>();

students.Add(new Student("Can", 30, Gender.Male, ["Fizik","Kimya"]));
students.Add(new Student("Zeynep", 24, Gender.Female, ["Kimya","Biyoloji", "Fizik"]));
students.Add(new Student("Emre", 18, Gender.Male, ["Tarih", "Matematik"]));
students.Add(new Student("Barış", 30, Gender.Male, ["Fizik", "Tarih"]));
students.Add(new Student("Haktan", 30, Gender.Male, ["Matematik", "Coğrafya"]));
students.Add(new Student("Melisa", 35, Gender.Male, ["Biyoloji", "Matematik"]));

var studentLessonMatch = students.SelectMany(s => s.Lessons, (student, lesson) => new { StudentName = student.Name, Age= student.Age, Lesson = lesson });

Console.WriteLine("Grade list:");

Console.WriteLine("Students Name - Age - Lesson list:");

foreach(var match in studentLessonMatch)
{
    Console.WriteLine($"{match.StudentName} - {match.Age} - {match.Lesson}");
}

//# Output:
Students' name - age - lesson list:
Can - 30 - Fizik
Can - 30 - Kimya
Zeynep - 24 - Kimya
Zeynep - 24 - Biyoloji
Zeynep - 24 - Fizik
Emre - 18 - Tarih
Emre - 18 - Matematik
Barış - 30 - Fizik
Barış - 30 - Tarih
Haktan - 30 - Matematik
Haktan - 30 - Coğrafya
Melisa - 35 - Biyoloji
Melisa - 35 - Matematik

3.Sorting (Sıralama)

Sıralama operatörleri veri koleksiyonundaki verileri belirli bir düzene göre sıralamak için kullanılmaktadır. LINQ'da sıralama işlemleri için OrderBy ve ThenBy ve Reverse operatörleri yaygın olarak kullanılmaktadır.

OrderBy operatörü belirli bir koşulu sağlayan öğeleri filtrelemek ve seçmek için kullanılmaktadır. OrderBy operatorü sıralamayı artan sıralama olarak yapmaktadır, azalan sıralama yapmak için OrderByDescending kullanılmaktadır. Koşullar lambda ifadeleri ile belirtilmektedir.

ThenBy operatörü OrderBy kullanımı sonrasında ikinci bir sıralama kriteri eklemek için kullanılmaktadır. Önceki sıralama sonucundaki öğeleri sıralamaktadır. ThenBy operatorü sıralamayı artan sıralama olarak yapmaktadır, azalan sıralama yapmak için ThenByDescending kullanılmaktadır. Koşullar lambda ifadeleri ile belirtilmektedir.

Reverse operatörü koleksiyonun sıralamasını tersine çevirmek için kullanılmaktadır.

OrderBy ve OrderByDescending operatörlerinin kullanımı için kod örneği:

List<Student> students = new List<Student>();

students.Add(new Student("Can", 30, Gender.Male, ["Fizik","Kimya"]));
students.Add(new Student("Zeynep", 24, Gender.Female, ["Kimya","Biyoloji", "Fizik"]));
students.Add(new Student("Emre", 18, Gender.Male, ["Tarih", "Matematik"]));
students.Add(new Student("Barış", 30, Gender.Male, ["Fizik", "Tarih"]));
students.Add(new Student("Haktan", 30, Gender.Male, ["Matematik", "Coğrafya"]));
students.Add(new Student("Melisa", 35, Gender.Male, ["Biyoloji", "Matematik"]));

var ascendingOrderStudents = students.OrderBy(s => s.Name).ToList();
var descendingOrderStudents = students.OrderByDescending(s => s.Name).ToList();

Console.WriteLine("OrderBy students list:");

foreach(var student in ascendingOrderStudents)
{
    Console.WriteLine(student.Name);
}

Console.WriteLine("OrderByDescending students list:");

foreach (var student in descendingOrderStudents)
{
    Console.WriteLine(student.Name);
}

//# Output:
OrderBy students list:
Barış
Can
Emre
Haktan
Melisa
Zeynep
OrderByDescending students list:
Zeynep
Melisa
Haktan
Emre
Can
Barış

ThenBy ve ThenByDescending operatörlerinin kullanımı için kod örneği:

//Record tipinde nesne oluşturalım
record Student(string Name, int Age, Gender Gender, IEnumerable<string> Lessons) { }

enum Gender
{
    Female,
    Male
}

List<Student> students = new List<Student>();

students.Add(new Student("Can", 21, Gender.Male, ["Fizik","Kimya"]));
students.Add(new Student("Zeynep", 24, Gender.Female, ["Kimya","Biyoloji", "Fizik"]));
students.Add(new Student("Emre", 18, Gender.Male, ["Tarih", "Matematik"]));
students.Add(new Student("Can", 30, Gender.Male, ["Fizik", "Tarih"]));
students.Add(new Student("Zeynep", 30, Gender.Male, ["Matematik", "Coğrafya"]));
students.Add(new Student("Melisa", 35, Gender.Male, ["Biyoloji", "Matematik"]));
students.Add(new Student("Melisa", 30, Gender.Male, ["Biyoloji", "Matematik"]));

var ascendingOrderStudents = students.OrderBy(s => s.Name).ThenBy(s => s.Age).ToList();
var descendingOrderStudents = students.OrderByDescending(s => s.Name).ThenByDescending(s => s.Age).ToList();

Console.WriteLine("OrderBy - ThenBy students list:");

foreach(var student in ascendingOrderStudents)
{
    Console.WriteLine($"{student.Name} - {student.Age}");
}

Console.WriteLine("OrderByDescending - ThenByDescending students list:");

foreach (var student in descendingOrderStudents)
{
    Console.WriteLine($"{student.Name} - {student.Age}");
}

// Output:
OrderBy - ThenBy students list:
Can - 21
Can - 30
Emre - 18
Melisa - 30
Melisa - 35
Zeynep - 24
Zeynep - 30
OrderByDescending - ThenByDescending students list:
Zeynep - 30
Zeynep - 24
Melisa - 35
Melisa - 30
Emre - 18
Can - 30
Can - 21

Reverse operatörü kullanımı için kod örneği:

//Record tipinde nesne oluşturalım
record Student(string Name, int Age, Gender Gender, IEnumerable<string> Lessons) { }

enum Gender
{
    Female,
    Male
}

List<Student> students = new List<Student>();

students.Add(new Student("Can", 21, Gender.Male, ["Fizik","Kimya"]));
students.Add(new Student("Zeynep", 24, Gender.Female, ["Kimya","Biyoloji", "Fizik"]));
students.Add(new Student("Emre", 18, Gender.Male, ["Tarih", "Matematik"]));
students.Add(new Student("Can", 30, Gender.Male, ["Fizik", "Tarih"]));
students.Add(new Student("Zeynep", 30, Gender.Male, ["Matematik", "Coğrafya"]));
students.Add(new Student("Melisa", 35, Gender.Male, ["Biyoloji", "Matematik"]));
students.Add(new Student("Melisa", 30, Gender.Male, ["Biyoloji", "Matematik"]));

//Reverse işlemi
var reversedStudents = students.AsEnumerable().Reverse();

Console.WriteLine("Students list:");

foreach(var student in students)
{
    Console.WriteLine(student.Name);
}

Console.WriteLine("Reversed students list:");

foreach (var student in reversedStudents)
{
    Console.WriteLine(student.Name);
}

//# Output:
Students list:
Can
Zeynep
Emre
Can
Zeynep
Melisa
Melisa
Reversed students list:
Melisa
Melisa
Zeynep
Can
Emre
Zeynep
Can

4.Joining (Birleştirme)

Birleştirme operatörleri iki veya daha fazla koleksiyonu birleştirerek koleksiyonlar arasındaki ilişkili verileri bir araya getirmektedir. LINQ'da birleştirme işlemleri için Join ve GroupJoin operatörleri yaygın olarak kullanılmaktadır.

Join operatörü iki koleksiyon arasında birleştirme işlemi yaparak koleksiyonlardaki verileri ilişkilendirmektedir. SQL INNER JOIN gibi işlevi bulunmaktadır.

GroupJoin operatörü iki koleksiyon arasında birleştirme işlemi yapar fakat birleştirilen öğeleri gruplar halinde döndürmektedir SQL GROUP JOIN gibi işlevi bulunmaktadır.

Join ve GroupJoin operatörlerinin kullanımı için kod örneği:

// Record tipinde nesne oluşturalım
record Student(int Id, string Name, int DepartmentId) { }

record Department(int Id, string Name) { }

List<Student> students = new List<Student>() {
    new Student( 1, "Ali", 1 ),
    new Student( 2, "Ayşe", 2 ),
    new Student( 3, "Mehmet", 1 ),
    new Student( 4, "Fatma", 3 ),
    new Student( 5, "Can", 2 ),
};

List<Department> departments = new List<Department> {
    new Department(1, "Bilgisayar Mühendisliği"),
    new Department(2, "Elektrik-Elektronik Mühendisliği"),
    new Department(3, "Makine Mühendisliği"),
};

// Birleştirilmiş listeyi yazdıralım
var joinQuery = students.Join(
    departments,
    student => student.DepartmentId,
    department => department.Id,
    (student, department) => new {
        StudentName = student.Name,
        DepartmentName = department.Name
    }
);

Console.WriteLine("Joined List:");
foreach (var item in joinQuery) {
    Console.WriteLine($"{item.StudentName} - {item.DepartmentName}");
}

//# Output:
Joined List:
Ali - Bilgisayar Mühendisliği
Ayşe - Elektrik-Elektronik Mühendisliği
Mehmet - Bilgisayar Mühendisliği
Fatma - Makine Mühendisliği
Can - Elektrik-Elektronik Mühendisliği


// Departman bazında öğrencileri gruplayalım
var groupJoinQuery = departments.GroupJoin(
    students,
    department => department.Id,
    student => student.DepartmentId,
    (department, studentsInDepartment) => new {
        DepartmentName = department.Name,
        Students = studentsInDepartment
    }
);

foreach (var department in groupJoinQuery) {
    Console.WriteLine($"{department.DepartmentName}:");
    foreach (var student in department.Students) {
        Console.WriteLine($"  - {student.Name}");
    }
}

//# Output:
Bilgisayar Mühendisliği:
  - Ali
  - Mehmet
Elektrik-Elektronik Mühendisliği:
  - Ayşe
  - Can
Makine Mühendisliği:
  - Fatma

5.Grouping (Gruplama)

Gruplama operatörleri koleksiyondaki öğeleri belirlenen kriter doğrultusunda gruplandırmak için kullanılmaktadır. LINQ'da gruplama işlemleri için GroupBy operatörü kullanılmaktadır.

GroupBy operatörü kullanımı için kod örneği:

record City(int Id, string Name, string CountryName);

List<City> cities = new List<City>
{
    new City(1,"Ankara", "Türkiye"),
    new City(2, "İstanbul", "Türkiye"),
    new City(3,"Paris", "Fransa"),
    new City(4, "Roma", "İtalya"),
    new City(5,"Lyon", "Fransa"),
    new City(6, "Londra", "İngiltere"),
    new City(7, "İzmir", "Türkiye"),
    new City(8, "Manchester", "İngiltere"),
    new City(9, "Milano", "İtalya"),
};

Console.WriteLine("Cities:");
foreach(var city in cities)
{
    Console.WriteLine($"{city.Name} - {city.CountryName}");
}

var groupedCities = cities.GroupBy(c => c.CountryName).ToList();

Console.WriteLine("Grouped Cities:");
foreach (var group in groupedCities)
{
    Console.WriteLine($"\nCountry: {group.Key}");
    foreach (var city in group)
    {
        Console.WriteLine($"City: {city.Name}");
    }
}

//# Output:
Ankara - Türkiye
İstanbul - Türkiye
Paris - Fransa
Roma - İtalya
Lyon - Fransa
Londra - İngiltere
İzmir - Türkiye
Manchester - İngiltere
Milano - İtalya

Grouped Cities:

Ülke:Türkiye
Şehir:Ankara
Şehir:İstanbul
Şehir:İzmir

Ülke:Fransa
Şehir:Paris
Şehir:Lyon

Ülke:İtalya
Şehir:Roma
Şehir:Milano

Ülke:İngiltere
Şehir:Londra
Şehir:Manchester

5.Aggregating (Toplama)

Toplama operatörleri koleksiyondaki öğeler üzerinden işlemler yaparak tek bir sonuç üretmek için kullanılmaktadır. LINQ'da toplama işlemleri için Sum, Count ve Average operatörleri yaygın olarak kullanılmaktadır.

Sum operatörü koleksiyondaki sayısal değerlerin toplanması için kullanılmaktadır.

Count operatörü koleksiyondaki eleman sayısını döndürmektedir. Öğe sayısı kontrolü için kullanılabilir.

Average operatörü koleksiyondaki sayısal değerlerin ortalamasını hesaplamaktadır.

Sum, Count ve Average operatörlerinin kullanımı için kod örneği:

record Employee(string Name, int Salary) { }

List<Employee> employees = new List<Employee>
{
    new Employee("Ahmet", 25000),
    new Employee("Nilgün", 22700),
    new Employee("Mehmet", 17800),
    new Employee("Zeynep", 35000),
    new Employee("Can", 28000),
    new Employee("Ali", 45750),
    new Employee("Gürkan", 55000),
    new Employee("Barış", 85860),
};

var totalSalary = employees.Sum(x => x.Salary);
var averageSalary = employees.Average(x => x.Salary);
var employeeCount = employees.Count();

Console.WriteLine($"Total salary: {totalSalary.ToString(\"N\", new CultureInfo(\"tr-TR\"))}");
Console.WriteLine($"Average salary: {averageSalary.ToString(\"N\", new CultureInfo(\"tr-TR\"))}");
Console.WriteLine($"Total employee count: {employeeCount}");

//# Output:
Total salary: 315.110,00
Average salary: 39.388,75
Total employee count: 8

LINQ Metot Örnekleri

1.SingleOrDefault() Yöntemi

SingleOrDefault yöntemi, bir koleksiyon üzerinde belirlenen koşula uyan yalnızca bir öğe varsa elemanı döndürmektedir. Koşula uyan herhangi bir öğe yok ise null değeri döndürür, koşula uyan birden fazla öğe var ise InvalidOperationException hatası fırlatır.

Kod örneği:

record Employee(string Name, int Salary) { }

List<Employee> employees = new List<Employee>
{
    new Employee("Ahmet", 25000),
    new Employee("Nilgün", 25000),
    new Employee("Mehmet", 17800),
    new Employee("Zeynep", 35000),
    new Employee("Can", 28000),
    new Employee("Ali", 45750),
    new Employee("Gürkan", 55000),
    new Employee("Barış", 85860),
};

//Birden fazla eleman döneceği için InvalidOperationException hatası fırlatır:
var result = employees.SingleOrDefault(x => x.Salary.Equals(25000));

//Koşula uyan öğe bulunmadığı için null döner:
var result2 = employees.SingleOrDefault(x => x.Salary.Equals(1000));

var result3 = employees.SingleOrDefault(x => x.Salary.Equals(28000));
Console.WriteLine($"{result3.Name} - {result3.Salary}");

//# Output:
Can - 28000

2.FirstOrDefault() Yöntemi

FirstOrDefault yöntemi, bir koleksiyon üzerinde belirlenen koşula uyan ilk öğeyi döndürmektedir. Koşula uyan herhangi bir öğe yok ise null değeri döndürür, koşula uyan birden fazla öğe var ise sadece ilk öğeyi almaktadır.

Kod örneği:

record Employee(string Name, int Salary) { }

List<Employee> employees = new List<Employee>
{
    new Employee("Ahmet", 25000),
    new Employee("Nilgün", 25000),
    new Employee("Mehmet", 17800),
    new Employee("Zeynep", 35000),
    new Employee("Can", 28000),
    new Employee("Ali", 45750),
    new Employee("Gürkan", 55000),
    new Employee("Barış", 85860),
};

//Birden fazla eleman döneceği için ilk elemanı alır -> Ahmet:
var result = employees.FirstOrDefault(x => x.Salary.Equals(25000));
Console.WriteLine($"{result.Name} - {result.Salary}");

//Koşula uyan öğe bulunmadığı için null döner:
var result2 = employees.FirstOrDefault(x => x.Salary.Equals(1000));

var result3 = employees.SingleOrDefault(x => x.Salary.Equals(28000));
Console.WriteLine($"{result3.Name} - {result3.Salary}");

//# Output:
Ahmet - 25000
Can - 28000

3.Concat() Yöntemi

Concat yöntemi, iki veya daha fazla koleksiyonu birleştirmek için kullanılmaktadır. Bir koleksiyondaki tüm öğeleri diğer koleksiyon öğeleri ile arka arkaya ekleyip ardışık şekilde birleştirmektedir. Birleştirme sırasında öğelerin tekrar edilmesi dikkate alınmaz, yani sonuç benzersiz öğeler içermeyip tekrar eden öğeler içerebilir.

Kod örneği:

record Person(string Name, int Age, Gender Gender) { }

enum Gender
{
    Female,
    Male
}

List<Person> women = new List<Person>
{
    new Person("Zeynep", 30, Gender.Female),
    new Person("Gülsu", 24, Gender.Female),
    new Person("Aylin", 18, Gender.Female),
    new Person("Deniz", 18, Gender.Female),
};

List<Person> men = new List<Person>
{
    new Person("Ahmet", 35, Gender.Male),
    new Person("Can", 30, Gender.Male),
    new Person("Barış", 29, Gender.Male),
    new Person("Haktan", 31, Gender.Male),
    new Person("Deniz", 18, Gender.Male),
};

var concatResult = men.Select(x => x.Name).Concat(women.Select(x => x.Name));

foreach (var person in concatResult) Console.WriteLine(person);

//# Output:
Ahmet
Can
Barış
Haktan
Deniz
Zeynep
Gülsu
Aylin
Deniz

4.Union() Yöntemi

Union yöntemi, iki veya daha fazla koleksiyonu birleştirmek için kullanılmaktadır. Concat metodundan farklı olarak birleştirilen koleksiyonlardaki öğeler benzersiz öğelerdir. Tekrar eden öğeler içeren koleksiyonlardaki tekrar eden elemanların bir kez yer almasının istenildiği durumlarda kullanılabilmektedir.

Kod örneği:

record Person(string Name, int Age, Gender Gender) { }

enum Gender
{
    Female,
    Male
}

List<Person> women = new List<Person>
{
    new Person("Zeynep", 30, Gender.Female),
    new Person("Gülsu", 24, Gender.Female),
    new Person("Aylin", 18, Gender.Female),
    new Person("Deniz", 18, Gender.Female),
};

List<Person> men = new List<Person>
{
    new Person("Ahmet", 35, Gender.Male),
    new Person("Can", 30, Gender.Male),
    new Person("Barış", 29, Gender.Male),
    new Person("Haktan", 31, Gender.Male),
    new Person("Deniz", 18, Gender.Male),
};

var unionResult = men.Select(x => x.Name).Union(women.Select(x => x.Name));

foreach (var person in unionResult) Console.WriteLine(person);

//# Output:
Ahmet
Can
Barış
Haktan
Deniz
Zeynep
Gülsu
Aylin

 Sonuç olarak LINQ veri kaynakları üzerinde sorgulama yapmayı ve çalışmayı daha kolay ve okunabilir hale getiren güçlü bir teknolojidir.