C Sharp LINQ 过滤
外观
C# LINQ 过滤[编辑 | 编辑源代码]
LINQ(Language Integrated Query)是C#中用于查询数据的强大工具,而过滤是LINQ中最常用的操作之一。通过过滤,可以从数据集合中筛选出符合特定条件的元素。本教程将详细介绍LINQ过滤的概念、语法、实际应用以及相关技巧。
介绍[编辑 | 编辑源代码]
LINQ过滤操作允许开发者使用简洁的语法从数据源(如数组、集合、数据库等)中提取满足特定条件的元素。最常见的过滤方法是使用Where子句,它接受一个谓词(返回布尔值的函数)作为参数,并返回所有满足该谓词的元素。
LINQ过滤可以应用于任何实现了IEnumerable<T>或IQueryable<T>接口的数据源,包括:
- 内存中的集合(如List、Array)
- 数据库(通过Entity Framework)
- XML文档
- 其他自定义数据源
基本语法[编辑 | 编辑源代码]
LINQ提供两种语法形式来执行过滤操作:查询语法和方法语法。
查询语法[编辑 | 编辑源代码]
查询语法类似于SQL,使用`where`关键字进行过滤:
from item in collection
where condition
select item;
方法语法[编辑 | 编辑源代码]
方法语法使用扩展方法,主要通过`Where()`方法:
collection.Where(item => condition);
两种语法在功能上是等价的,编译器会将查询语法转换为方法语法。
代码示例[编辑 | 编辑源代码]
示例1:基本过滤[编辑 | 编辑源代码]
以下示例演示如何从一个整数列表中筛选出偶数:
List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
// 查询语法
var evenNumbersQuery = from num in numbers
where num % 2 == 0
select num;
// 方法语法
var evenNumbersMethod = numbers.Where(num => num % 2 == 0);
// 输出结果
Console.WriteLine("偶数:");
foreach (var num in evenNumbersMethod)
{
Console.WriteLine(num);
}
输出:
偶数: 2 4 6 8 10
示例2:复杂条件过滤[编辑 | 编辑源代码]
可以组合多个条件进行更复杂的过滤:
List<string> fruits = new List<string>
{
"Apple", "Banana", "Cherry", "Date", "Elderberry", "Fig", "Grape"
};
// 长度大于3且包含字母'a'的水果
var filteredFruits = fruits.Where(f => f.Length > 3 && f.ToLower().Contains('a'));
foreach (var fruit in filteredFruits)
{
Console.WriteLine(fruit);
}
输出:
Banana Cherry Elderberry Grape
实际应用案例[编辑 | 编辑源代码]
案例1:电子商务产品过滤[编辑 | 编辑源代码]
假设有一个电子商务网站,需要根据用户选择的条件过滤产品:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public string Category { get; set; }
public int Stock { get; set; }
}
List<Product> products = new List<Product>
{
new Product { Id = 1, Name = "Laptop", Price = 999.99m, Category = "Electronics", Stock = 10 },
new Product { Id = 2, Name = "Smartphone", Price = 699.99m, Category = "Electronics", Stock = 15 },
new Product { Id = 3, Name = "Desk Chair", Price = 199.99m, Category = "Furniture", Stock = 5 },
new Product { Id = 4, Name = "Coffee Mug", Price = 9.99m, Category = "Kitchen", Stock = 20 }
};
// 用户过滤条件
decimal maxPrice = 500.00m;
string desiredCategory = "Electronics";
int minStock = 5;
var filteredProducts = products.Where(p =>
p.Price <= maxPrice &&
p.Category == desiredCategory &&
p.Stock >= minStock);
Console.WriteLine("符合条件的商品:");
foreach (var product in filteredProducts)
{
Console.WriteLine($"{product.Name} - ${product.Price}");
}
输出:
符合条件的商品: Smartphone - $699.99
案例2:日志文件分析[编辑 | 编辑源代码]
从日志条目中筛选出特定级别的错误:
public class LogEntry
{
public DateTime Timestamp { get; set; }
public string Level { get; set; }
public string Message { get; set; }
}
List<LogEntry> logs = new List<LogEntry>
{
new LogEntry { Timestamp = DateTime.Now.AddHours(-1), Level = "INFO", Message = "System started" },
new LogEntry { Timestamp = DateTime.Now.AddMinutes(-30), Level = "WARNING", Message = "Disk space low" },
new LogEntry { Timestamp = DateTime.Now.AddMinutes(-5), Level = "ERROR", Message = "Database connection failed" }
};
// 只显示ERROR级别的日志
var errorLogs = logs.Where(log => log.Level == "ERROR");
foreach (var log in errorLogs)
{
Console.WriteLine($"[{log.Level}] {log.Timestamp}: {log.Message}");
}
输出:
[ERROR] 5/15/2023 2:55:00 PM: Database connection failed
高级过滤技巧[编辑 | 编辑源代码]
动态过滤[编辑 | 编辑源代码]
可以使用变量动态构建过滤条件:
Func<Product, bool> filter = p => true; // 初始化为不过滤
// 根据用户输入动态添加条件
if (userWantsElectronics)
filter = p => p.Category == "Electronics";
if (userHasMaxPrice)
filter = p => filter(p) && p.Price <= userMaxPrice;
var results = products.Where(filter);
使用索引过滤[编辑 | 编辑源代码]
`Where`方法有一个重载版本可以接受元素的索引:
// 只选择偶数索引位置的元素
var everyOther = numbers.Where((num, index) => index % 2 == 0);
性能考虑[编辑 | 编辑源代码]
- 延迟执行:LINQ查询通常是延迟执行的,只有在实际枚举结果时才会应用过滤条件。
- 多次枚举:如果多次枚举同一个查询结果,过滤条件会重复执行。可以使用`ToList()`或`ToArray()`缓存结果。
- IQueryable vs IEnumerable:对于数据库查询,`IQueryable`会将过滤条件转换为SQL,在数据库端执行,效率更高。
常见问题[编辑 | 编辑源代码]
空集合处理[编辑 | 编辑源代码]
对null集合调用LINQ方法会抛出异常。可以使用空集合模式:
var safeCollection = possiblyNullCollection ?? Enumerable.Empty<T>();
var filtered = safeCollection.Where(...);
区分null和空字符串[编辑 | 编辑源代码]
// 只选择非null且非空的字符串
var validStrings = stringCollection.Where(s => !string.IsNullOrEmpty(s));
总结[编辑 | 编辑源代码]
LINQ过滤是处理数据集合的强大工具,通过`Where`方法可以简洁地表达复杂的过滤逻辑。关键点包括:
- 两种语法形式(查询语法和方法语法)
- 支持简单和复杂的过滤条件
- 延迟执行特性
- 适用于各种数据源
- 提供动态构建查询的能力
掌握LINQ过滤将显著提高你的C#编程效率和代码可读性。