C# LINQ语法学习

LINQ(Language Integrated Query)是一种内置于 C# 和 .NET 中的数据查询工具。它允许开发者以类似于 SQL 的语法来查询内存对象、数据库、XML 文件等数据源。以下是一个详细的 LINQ 教程,涵盖了从基础到高级的内容。

一、LINQ 基础

LINQ 的基本操作可以用两种语法来表达:

  • 查询表达式语法(Query Syntax):类似于 SQL 查询语法。
  • 方法语法 (Method Syntax):使用扩展方法(如 WhereSelect 等)进行查询。

这两种语法功能相同,可以互换使用。

1. 示例:查询表达式语法
csharp 复制代码
int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

// 查询所有偶数
var evenNumbers = from num in numbers
                  where num % 2 == 0
                  select num;

foreach (var number in evenNumbers)
{
    Console.WriteLine(number);
}
2. 示例:方法语法
csharp 复制代码
int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

// 使用方法语法查询所有偶数
var evenNumbers = numbers.Where(num => num % 2 == 0);

foreach (var number in evenNumbers)
{
    Console.WriteLine(number);
}

二、LINQ 的主要操作符

LINQ 包含多种操作符,常见的有过滤、排序、投影、集合操作、分组、连接和聚合。

1. 过滤操作符
  • Where:用于根据条件筛选数据。
csharp 复制代码
int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

// 筛选大于 5 的数字
var filteredNumbers = numbers.Where(n => n > 5);
2. 排序操作符
  • OrderByOrderByDescending:用于升序和降序排序。
csharp 复制代码
string[] names = { "Alice", "Bob", "Charlie", "David" };

// 按名字升序排序
var sortedNames = names.OrderBy(n => n);

// 按名字降序排序
var descendingNames = names.OrderByDescending(n => n);
  • ThenByThenByDescending:用于多重排序。
csharp 复制代码
var people = new List<Person>
{
    new Person { FirstName = "John", LastName = "Doe" },
    new Person { FirstName = "Jane", LastName = "Smith" },
    new Person { FirstName = "John", LastName = "Smith" }
};

// 先按姓氏排序,再按名字排序
var sortedPeople = people.OrderBy(p => p.LastName).ThenBy(p => p.FirstName);
3. 投影操作符
  • Select:用于选择集合中的元素或其某些部分。
csharp 复制代码
var squares = numbers.Select(n => n * n);
  • SelectMany:将每个元素的结果展开为一个集合。
csharp 复制代码
List<int[]> numberLists = new List<int[]> { new[] { 1, 2 }, new[] { 3, 4 }, new[] { 5, 6 } };

// 使用 SelectMany 展开成单个集合
var allNumbers = numberLists.SelectMany(n => n);
4. 集合操作符
  • Distinct:用于去除重复元素。
  • UnionIntersectExcept:分别用于集合的并集、交集、差集。
csharp 复制代码
int[] numbers1 = { 1, 2, 3 };
int[] numbers2 = { 3, 4, 5 };

// 获取并集
var union = numbers1.Union(numbers2); // 结果为 {1, 2, 3, 4, 5}

// 获取交集
var intersect = numbers1.Intersect(numbers2); // 结果为 {3}

// 获取差集
var except = numbers1.Except(numbers2); // 结果为 {1, 2}
5. 聚合操作符
  • CountSumAverageMinMax:用于对集合进行数学运算。
csharp 复制代码
int[] numbers = { 1, 2, 3, 4, 5 };

// 计算总数
int count = numbers.Count();

// 计算总和
int sum = numbers.Sum();

// 计算平均值
double average = numbers.Average();
6. 分组操作符
  • GroupBy:根据某个键将集合分组。
csharp 复制代码
string[] words = { "apple", "banana", "cherry", "date", "elderberry" };

// 根据单词的长度分组
var groupedWords = words.GroupBy(word => word.Length);

foreach (var group in groupedWords)
{
    Console.WriteLine($"Length: {group.Key}");
    foreach (var word in group)
    {
        Console.WriteLine(word);
    }
}
7. 连接操作符
  • Join:用于连接两个集合。
csharp 复制代码
var categories = new List<Category>
{
    new Category { Id = 1, Name = "Beverages" },
    new Category { Id = 2, Name = "Snacks" }
};

var products = new List<Product>
{
    new Product { Name = "Tea", CategoryId = 1 },
    new Product { Name = "Coffee", CategoryId = 1 },
    new Product { Name = "Chips", CategoryId = 2 }
};

// 根据 CategoryId 连接 categories 和 products
var query = from c in categories
            join p in products on c.Id equals p.CategoryId
            select new { c.Name, p.Name };

foreach (var item in query)
{
    Console.WriteLine($"{item.Name} - {item.Name}");
}

三、LINQ 的延迟执行和立即执行

LINQ 查询默认是延迟执行的,意味着在真正遍历查询结果时才会执行查询操作。

延迟执行
csharp 复制代码
var query = numbers.Where(n => n > 5);

// 此时查询并未执行
立即执行

可以使用 ToList()ToArray()Count() 等方法来立即执行查询。

csharp 复制代码
var resultList = numbers.Where(n => n > 5).ToList(); // 查询在此时执行

四、LINQ 的高级功能

1. 使用 let 关键字

let 可以用于定义临时变量,使查询更加简洁。

csharp 复制代码
var query = from word in words
            let length = word.Length
            where length > 3
            select new { word, length };
2. 使用匿名类型

可以使用匿名类型来创建临时的结果对象。

csharp 复制代码
var results = from word in words
              select new { Word = word, Length = word.Length };
3. 使用 Lambda 表达式和扩展方法

方法语法通常使用 Lambda 表达式,可以实现非常复杂的查询。

csharp 复制代码
var query = words.Where(w => w.Length > 3)
                 .OrderBy(w => w)
                 .Select(w => new { Word = w, Length = w.Length });
4. 混合使用查询表达式和方法语法

在同一个查询中,可以混合使用查询表达式和方法语法。

csharp 复制代码
var query = (from num in numbers
             where num > 5
             select num).Sum();

五、实战:LINQ 查询数据库

LINQ 也可以用于查询数据库,通常结合 Entity Framework 使用。以下是一个查询数据库的例子:

csharp 复制代码
using (var context = new MyDbContext())
{
    var customers = from c in context.Customers
                    where c.City == "New York"
                    select c;

    foreach (var customer in customers)
    {
        Console.WriteLine(customer.Name);
    }
}

总结

  • LINQ 提供了类似 SQL 的查询语法和方法语法,可以方便地对各种数据源进行操作。
  • 它支持过滤、排序、分组、连接、投影等操作,具有强大的数据处理能力。
  • 延迟执行是 LINQ 的一个特点,能提高查询效率,但也需要注意可能的副作用。
  • 在实际开发中,可以结合 Entity Framework 等技术来处理数据库查询。

LINQ 的学习曲线较平缓,但掌握其高级功能和应用场景会显著提升开发效率。

相关推荐
军训猫猫头32 分钟前
20.抽卡只有金,带保底(WPF) C#
ui·c#·wpf
A懿轩A32 分钟前
C/C++ 数据结构与算法【数组】 数组详细解析【日常学习,考研必备】带图+详细代码
c语言·数据结构·c++·学习·考研·算法·数组
南宫生8 小时前
力扣-图论-17【算法学习day.67】
java·学习·算法·leetcode·图论
sanguine__9 小时前
Web APIs学习 (操作DOM BOM)
学习
向宇it11 小时前
【从零开始入门unity游戏开发之——C#篇25】C#面向对象动态多态——virtual、override 和 base 关键字、抽象类和抽象方法
java·开发语言·unity·c#·游戏引擎
数据的世界0111 小时前
.NET开发人员学习书籍推荐
学习·.net
四口鲸鱼爱吃盐11 小时前
CVPR2024 | 通过集成渐近正态分布学习实现强可迁移对抗攻击
学习
向宇it12 小时前
【从零开始入门unity游戏开发之——C#篇24】C#面向对象继承——万物之父(object)、装箱和拆箱、sealed 密封类
java·开发语言·unity·c#·游戏引擎
OopspoO13 小时前
qcow2镜像大小压缩
学习·性能优化
A懿轩A14 小时前
C/C++ 数据结构与算法【栈和队列】 栈+队列详细解析【日常学习,考研必备】带图+详细代码
c语言·数据结构·c++·学习·考研·算法·栈和队列