C# LINQ Introduction
What is LINQ?
LINQ (Language Integrated Query) is one of the most powerful features in C#. Introduced in .NET Framework 3.5 and C# 3.0, LINQ provides a unified way to query different types of data sources, such as collections, databases, XML, and more.
Before LINQ, querying data in C# involved writing different code for different data sources - SQL for databases, XPath for XML, and custom loops for collections. LINQ brings all these under one consistent approach, allowing you to use the same syntax regardless of the data source.
Why Learn LINQ?
LINQ offers several advantages that make it essential for C# developers:
- Readability: LINQ queries are more concise and readable than traditional loops
- Type Safety: Compile-time error checking prevents many runtime errors
- Consistency: Same syntax for querying different data sources
- Productivity: Fewer lines of code for complex data operations
- Powerful Operations: Easy implementation of filtering, sorting, grouping, joining, and more
LINQ Execution Methods
There are two primary ways to write LINQ queries in C#:
- Query Syntax: Similar to SQL, using keywords like
from
,where
, andselect
- Method Syntax: Using extension methods like
Where()
,Select()
, andOrderBy()
Let's explore both approaches with simple examples.
Basic LINQ Query Examples
Let's start with a simple collection of numbers:
// Creating a collection to query
int[] numbers = { 1, 5, 3, 9, 8, 6, 7, 2, 4 };
Query Syntax Example
// Using query syntax to find even numbers
var evenNumbers = from num in numbers
where num % 2 == 0
orderby num
select num;
// Displaying results
Console.WriteLine("Even numbers in ascending order:");
foreach (var number in evenNumbers)
{
Console.WriteLine(number);
}
Output:
Even numbers in ascending order:
2
4
6
8
Method Syntax Example
// Using method syntax to find even numbers
var evenNumbers = numbers.Where(n => n % 2 == 0).OrderBy(n => n);
// Displaying results
Console.WriteLine("Even numbers in ascending order:");
foreach (var number in evenNumbers)
{
Console.WriteLine(number);
}
Output:
Even numbers in ascending order:
2
4
6
8
As you can see, both approaches produce the same result. The choice between query syntax and method syntax is often a matter of personal preference, though method syntax tends to be more commonly used in professional development.
Common LINQ Operations
Let's explore some of the most common LINQ operations with examples:
Filtering (Where)
Filtering allows you to select elements that meet specific criteria:
string[] names = { "Alice", "Bob", "Charlie", "Dave", "Eve", "Frank", "Anna" };
// Find names that start with 'A'
var namesStartingWithA = names.Where(name => name.StartsWith("A"));
Console.WriteLine("Names starting with A:");
foreach (var name in namesStartingWithA)
{
Console.WriteLine(name);
}
Output:
Names starting with A:
Alice
Anna
Ordering (OrderBy, OrderByDescending)
Ordering allows you to sort elements based on a key:
// Order names by length, then alphabetically
var orderedNames = names
.OrderBy(name => name.Length)
.ThenBy(name => name);
Console.WriteLine("Names ordered by length then alphabetically:");
foreach (var name in orderedNames)
{
Console.WriteLine($"{name} ({name.Length} letters)");
}
Output:
Names ordered by length then alphabetically:
Bob (3 letters)
Eve (3 letters)
Anna (4 letters)
Dave (4 letters)
Alice (5 letters)
Frank (5 letters)
Charlie (7 letters)
Projection (Select)
Projection transforms each element into a new form:
// Transform names to uppercase and include their length
var transformedNames = names.Select(name => new {
UppercaseName = name.ToUpper(),
Length = name.Length
});
Console.WriteLine("Transformed names:");
foreach (var item in transformedNames)
{
Console.WriteLine($"{item.UppercaseName} has {item.Length} letters");
}
Output:
Transformed names:
ALICE has 5 letters
BOB has 3 letters
CHARLIE has 7 letters
DAVE has 4 letters
EVE has 3 letters
FRANK has 5 letters
ANNA has 4 letters
Aggregation (Count, Sum, Min, Max, Average)
LINQ provides methods for common aggregate operations:
int[] scores = { 78, 92, 65, 89, 76, 83, 95, 58 };
int count = scores.Count();
int sum = scores.Sum();
double average = scores.Average();
int minimum = scores.Min();
int maximum = scores.Max();
Console.WriteLine($"Count: {count}");
Console.WriteLine($"Sum: {sum}");
Console.WriteLine($"Average: {average}");
Console.WriteLine($"Minimum: {minimum}");
Console.WriteLine($"Maximum: {maximum}");
Output:
Count: 8
Sum: 636
Average: 79.5
Minimum: 58
Maximum: 95
Real-world Example: Managing a Product Catalog
Let's apply LINQ to a more realistic scenario - managing a product catalog:
// Product class
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public string Category { get; set; }
public decimal Price { get; set; }
public int Stock { get; set; }
}
// Creating a product catalog
List<Product> products = new List<Product>
{
new Product { Id = 1, Name = "Laptop", Category = "Electronics", Price = 1200.00m, Stock = 15 },
new Product { Id = 2, Name = "Smartphone", Category = "Electronics", Price = 800.00m, Stock = 25 },
new Product { Id = 3, Name = "Headphones", Category = "Electronics", Price = 100.00m, Stock = 50 },
new Product { Id = 4, Name = "T-shirt", Category = "Clothing", Price = 25.00m, Stock = 100 },
new Product { Id = 5, Name = "Jeans", Category = "Clothing", Price = 45.00m, Stock = 75 },
new Product { Id = 6, Name = "Coffee maker", Category = "Kitchen", Price = 150.00m, Stock = 30 },
new Product { Id = 7, Name = "Blender", Category = "Kitchen", Price = 80.00m, Stock = 20 },
new Product { Id = 8, Name = "Book", Category = "Books", Price = 20.00m, Stock = 60 }
};
// Find electronic products with price < 1000
var affordableElectronics = products
.Where(p => p.Category == "Electronics" && p.Price < 1000)
.OrderBy(p => p.Price);
Console.WriteLine("Affordable Electronics:");
foreach (var product in affordableElectronics)
{
Console.WriteLine($"{product.Name} - ${product.Price}");
}
// Group products by category and find average price per category
var categorySummary = products
.GroupBy(p => p.Category)
.Select(g => new {
Category = g.Key,
AveragePrice = g.Average(p => p.Price),
TotalItems = g.Sum(p => p.Stock)
})
.OrderByDescending(x => x.TotalItems);
Console.WriteLine("\nCategory Summary:");
foreach (var category in categorySummary)
{
Console.WriteLine($"{category.Category}: Avg Price: ${category.AveragePrice:F2}, Total Stock: {category.TotalItems}");
}
// Find products that need restocking (less than 30 items)
var lowStockProducts = products
.Where(p => p.Stock < 30)
.Select(p => new { p.Id, p.Name, p.Stock });
Console.WriteLine("\nProducts to Restock:");
foreach (var product in lowStockProducts)
{
Console.WriteLine($"ID: {product.Id}, {product.Name} - {product.Stock} in stock");
}
Output:
Affordable Electronics:
Headphones - $100.00
Smartphone - $800.00
Category Summary:
Clothing: Avg Price: $35.00, Total Stock: 175
Electronics: Avg Price: $700.00, Total Stock: 90
Kitchen: Avg Price: $115.00, Total Stock: 50
Books: Avg Price: $20.00, Total Stock: 60
Products to Restock:
ID: 1, Laptop - 15 in stock
ID: 2, Smartphone - 25 in stock
ID: 7, Blender - 20 in stock
This example demonstrates how LINQ can help you efficiently manage data in a business application, allowing you to filter, sort, group, and analyze data with minimal code.
Summary
In this introduction to LINQ, we've covered:
- What LINQ is and why it's valuable in C# development
- Two syntax options: query syntax and method syntax
- Basic LINQ operations: filtering, ordering, projection, and aggregation
- A practical example showing how LINQ can be used in a real-world application
LINQ is a powerful tool that simplifies complex data operations and helps you write more maintainable code. As you become more comfortable with LINQ, you'll find yourself writing less code to accomplish more complex tasks.
Additional Resources
- Microsoft's Official LINQ Documentation
- 101 LINQ Examples
- LINQPad - A great tool for testing LINQ queries
Exercises
-
Create a string array with at least 10 words and use LINQ to find all words that:
- Contain the letter 'e'
- Have exactly 5 letters
- Start with 'a' or 'A'
-
Create a list of
Person
objects with properties forName
,Age
, andCity
. Use LINQ to:- Find all people from a specific city
- Calculate the average age
- Group people by city and count how many people live in each city
-
Using the
Product
class from our real-world example, extend the example to:- Find the most expensive product in each category
- Calculate the total inventory value (price * stock for all products)
- Find products that have "phone" in their name (case-insensitive)
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)