集合中常用的查询方法
- 测试数据准备:
- 查询方法详解
- **Where**条件查询
- 定义和注释:
- 功能
- 详细说明:
- 应用实例
- 查找所有设备类型为“生产设备”的对象
- 结果测试:
- 查询所有测试结果大于90的设备
- 多条件查询:类型为生产设备同时测试结果大于90的设备
- **First/FirstOrDefault**
- 功能:
- 示例:
- 查找id为xxx的设备
- 查询id大于200的设备
- 方法区别:
- 示例:查找一个不存在的设备
- 定义和注释:
- **All**
- 功能:
- 示例:
- 查询是否所有设备都达标(测试结果大于90)
- **Any**
- 功能:
- 示例:
- **Count**
- 功能:
- 示例:
- 获集合数量
- 获取生产设备的数量
- 总结
- 完整示例
本篇介绍集合的各种查询方法和使用
主要介绍条件查询Where,单个对象查询First/FirstOrDefault、功能查询All、Any、Count等
测试数据准备:
定义 一个Device
类,包括设备ID,名称,类型和测试结果,然后初始化添加4条数据
/// <summary>
/// 设备类
/// </summary>
class Device
{
/// <summary>
/// Id
/// </summary>
public int Id { get; set; }
/// <summary>
/// 设备类型
/// </summary>
public string Type { get; set; }
/// <summary>
/// 名称
/// </summary>
public string Name { get; set; }
/// <summary>
/// 测试结果
/// </summary>
public int Result { get; set; }
}
//初始化数据
List<Device> list = new List<Device>();
list.Add(new Device() { Id = 101, Name = "1号设备", Type = "生产设备", Result = 99 });
list.Add(new Device() { Id = 102, Name = "2号设备", Type = "生产设备", Result = 60 });
list.Add(new Device() { Id = 103, Name = "3号设备", Type = "测试设备", Result = 98 });
list.Add(new Device() { Id = 104, Name = "4号设备", Type = "测试设备", Result = 70 });
list.Add(new Device() { Id = 201, Name = "5号生产设备", Type = "生产设备", Result = 100 });
list.Add(new Device() { Id = 202, Name = "6号测试设备", Type = "测试设备", Result = 89 });
list.Add(new Device() { Id = 203, Name = "7号测试设备", Type = "测试设备", Result = 98 });
list.Add(new Device() { Id = 204, Name = "8号测试设备", Type = "测试设备", Result = 95 });
当然,让我详细介绍一下这些常用的 LINQ 查询方法:
查询方法详解
Where条件查询
定义和注释:
// 摘要:
// 根据条件过滤序列中的值。
//
// 参数:
// source:
// 要过滤的 IEnumerable`1 类型的序列。
//
// predicate:
// 测试每个元素是否满足条件的函数。
//
// 类型参数:
// TSource:
// 序列中元素的类型。
//
// 返回结果:
// 包含输入序列中满足条件的元素的 IEnumerable`1。
//
// 异常:
// T:System.ArgumentNullException:
// source 或 predicate 为 null。
public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate);
// 摘要:
// 基于条件过滤序列中的值。每个元素的索引在谓词函数的逻辑中被使用。
//
// 参数:
// source:
// 要过滤的 IEnumerable`1 类型的序列。
//
// predicate:
// 测试源元素是否满足条件的函数;函数的第二个参数代表源元素的索引。
//
// 类型参数:
// TSource:
// 序列中元素的类型。
//
// 返回结果:
// 包含来自输入序列中满足条件的元素的 IEnumerable`1。
//
// 异常:
// T:System.ArgumentNullException:
// source 或 predicate 为 null。
public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, int, bool> predicate);
功能
用于过滤集合中的元素,返回一个新的集合,其中包含满足指定条件的所有元素。
详细说明:
该方法适用于所有继承于IEnumerable<TSource>
的集合,传入参数为一个Func<TSource, bool> predicate
委托,可以是一个参数为TSource
类型,返回值为bool
的方法或者Lambda表达式;方法返回一个新的IEnumerable<TSource>
的集合。
应用实例
查找所有设备类型为“生产设备”的对象
//Lambda
var productionDevices = list.Where(device => device.Type == "生产设备");
//方法
var productionDevices2 = list.Where(ProductDevice);
bool ProductDevice(Device device)
{
return device.Type == "生产设备";
}
结果测试:
将结果打印出来,可以看到上面两种方法效果一致,后续不一一演示两种方法,以Lambda的形式为主。
运行结果:
查询所有测试结果大于90的设备
var device90s = list.Where(device => device.Result >= 90);
多条件查询:类型为生产设备同时测试结果大于90的设备
var pro90Devices = list.Where(x => x.Type == "生产设备" && x.Result >= 90);
First/FirstOrDefault
功能:
返回集合中的第一个元素,如果集合为空,First
方法会抛出异常,而 FirstOrDefault
会返回该类型的默认值。
示例:
查找id为xxx的设备
var dev1 = list.First(x => x.Id == 101);
var dev2 = list.FirstOrDefault(x => x.Id == 101);
Console.WriteLine("\n单设备查找:");
Console.WriteLine($"ID: {dev1.Id}, 名称: {dev1.Name}, 结果: {dev1.Result}");
Console.WriteLine($"ID: {dev2.Id}, 名称: {dev2.Name}, 结果: {dev2.Result}");
查询id大于200的设备
var dev1 = list.First(x => x.Id > 200);
此时有多个满足的设备,但是他只会返回第一个
方法区别:
First
方法会抛出异常,而 FirstOrDefault
会返回该类型的默认值。
示例:查找一个不存在的设备
var dev2 = list.FirstOrDefault(x => x.Id == 0);
var dev1 = list.First(x => x.Id == 0);
可以看到使用FirstOrDefault
返回了一个null,也就是这个类型的默认值,而使用First
直接报错了,这个就根据自己需要去使用不同方法
定义和注释:
// 摘要:
// 返回序列中的第一个元素。
//
// 参数:
// source:
// 要从中返回第一个元素的 IEnumerable`1 序列。
//
// 类型参数:
// TSource:
// 序列中元素的类型。
//
// 返回结果:
// 序列中的第一个元素。
//
// 异常:
// T:System.ArgumentNullException:
// source 为 null。
//
// T:System.InvalidOperationException:
// 序列为空。
public static TSource First<TSource>(this IEnumerable<TSource> source);
// 摘要:
// 返回序列中满足指定条件的第一个元素。
//
// 参数:
// source:
// 要从中返回元素的 IEnumerable`1 序列。
//
// predicate:
// 测试每个元素是否满足条件的函数。
//
// 类型参数:
// TSource:
// 序列中元素的类型。
//
// 返回结果:
// 序列中通过指定谓词函数测试的第一个元素。
//
// 异常:
// T:System.ArgumentNullException:
// source 或 predicate 为 null。
//
// T:System.InvalidOperationException:
// 没有元素满足谓词条件。 - 或 - 序列为空。
public static TSource First<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate);
// 摘要:
// 返回序列中的第一个元素,如果序列不包含元素,则返回默认值。
//
// 参数:
// source:
// 要从中返回第一个元素的 IEnumerable`1 序列。
//
// 类型参数:
// TSource:
// 序列中元素的类型。
//
// 返回结果:
// 如果序列为空,则返回 default(TSource);否则,返回序列中的第一个元素。
//
// 异常:
// T:System.ArgumentNullException:
// source 为 null。
public static TSource? FirstOrDefault<TSource>(this IEnumerable<TSource> source);
// 摘要:
// 返回序列中的第一个元素,如果序列不包含元素,则返回默认值。
//
// 参数:
// source:
// 要从中返回第一个元素的 IEnumerable`1 序列。
//
// defaultValue:
// 序列为空时返回的默认值。
//
// 类型参数:
// TSource:
// 序列中元素的类型。
//
// 返回结果:
// 如果序列为空,则返回 defaultValue;否则,返回序列中的第一个元素。
//
// 异常:
// T:System.ArgumentNullException:
// source 为 null。
public static TSource FirstOrDefault<TSource>(this IEnumerable<TSource> source, TSource defaultValue);
// 摘要:
// 返回序列中满足条件的第一个元素或默认值,如果没有这样的元素则返回默认值。
//
// 参数:
// source:
// 要从中返回元素的 IEnumerable`1 序列。
//
// predicate:
// 测验每个元素是否满足条件的函数。
//
// 类型参数:
// TSource:
// 序列中元素的类型。
//
// 返回结果:
// 如果序列为空或没有任何元素通过谓词测试,则返回 default(TSource);否则,返回序列中通过谓词测试的第一个元素。
//
// 异常:
// T:System.ArgumentNullException:
// source 或 predicate 为 null。
public static TSource? FirstOrDefault<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate);
// 摘要:
// 返回序列中满足条件的第一个元素或默认值,如果没有这样的元素则返回默认值。
//
// 参数:
// source:
// 要从中返回元素的 IEnumerable`1 序列。
//
// predicate:
// 测验每个元素是否满足条件的函数。
//
// defaultValue:
// 如果序列为空时返回的默认值。
//
// 类型参数:
// TSource:
// 序列中元素的类型。
//
// 返回结果:
// 如果序列为空或没有任何元素通过谓词测试,则返回 defaultValue;否则,返回序列中通过谓词测试的第一个元素。
//
// 异常:
// T:System.ArgumentNullException:
// source 或 predicate 为 null。
public static TSource FirstOrDefault<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate, TSource defaultValue);
All
功能:
检查集合中的所有元素是否都满足指定条件。
示例:
查询是否所有设备都达标(测试结果大于90)
var result = list.All(x => x.Result > 90);
Any
功能:
检查集合中是否至少有一个元素满足指定条件。
示例:
查询是否有大于等于一个设备都达标(测试结果大于90)
var result2 = list.Any(x => x.Result > 90);
Count
功能:
返回满足指定条件的元素数量。
示例:
获集合数量
不加任何参数就是返回集合中对象的数量
var count = list.Count();
获取生产设备的数量
var count2 = list.Count(device => device.Type == "生产设备");
总结
看了上面这些示例,可以发现,有些查询条件都是类似的,不同方法,用法都是一样的,属于一个类似if
中的判断表达式,作为Lambda表达式主体,就可以达到效果,不同的方法就是查询的结果和功能不同。
完整示例
这些方法在处理集合时非常有用,特别是当你需要对集合进行条件筛选、查找单个元素或者统计信息时。
下面是使用这些方法的完整示例:
internal class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello, World!");
List<Device> list = new List<Device>();
list.Add(
new Device()
{
Id = 101,
Name = "1号设备",
Type = "生产设备",
Result = 99
}
);
list.Add(
new Device()
{
Id = 102,
Name = "2号设备",
Type = "生产设备",
Result = 60
}
);
list.Add(
new Device()
{
Id = 103,
Name = "3号设备",
Type = "测试设备",
Result = 98
}
);
list.Add(
new Device()
{
Id = 104,
Name = "4号设备",
Type = "测试设备",
Result = 70
}
);
list.Add(
new Device()
{
Id = 201,
Name = "5号生产设备",
Type = "生产设备",
Result = 100
}
);
list.Add(
new Device()
{
Id = 202,
Name = "6号测试设备",
Type = "测试设备",
Result = 89
}
);
list.Add(
new Device()
{
Id = 203,
Name = "7号测试设备",
Type = "测试设备",
Result = 98
}
);
list.Add(
new Device()
{
Id = 204,
Name = "8号测试设备",
Type = "测试设备",
Result = 95
}
);
// 使用LINQ查询方法
// 1. 选择所有设备名称
var deviceNames = list.Select(device => device.Name);
// 输出结果
Console.WriteLine("\n所有设备名称:");
foreach (var name in deviceNames)
{
Console.WriteLine(name);
}
// 过滤生产设备
var productionDevices = list.Where(device => device.Type == "生产设备");
var productionDevices2 = list.Where(ProductDevice);
Console.WriteLine("\n生产设备:");
foreach (var device in productionDevices)
{
Console.WriteLine($"ID: {device.Id}, 名称: {device.Name}, 结果: {device.Result}");
}
Console.WriteLine("\n生产设备:");
foreach (var device in productionDevices2)
{
Console.WriteLine($"ID: {device.Id}, 名称: {device.Name}, 结果: {device.Result}");
}
//Where
var device90s = list.Where(device => device.Result >= 90);
Console.WriteLine("\n生产合格设备:");
foreach (var device in device90s)
{
Console.WriteLine($"ID: {device.Id}, 名称: {device.Name}, 结果: {device.Result}");
}
var pro90Devices = list.Where(x => x.Type == "生产设备" && x.Result >= 90);
//First/FirstOrDefault
var dev1 = list.First(x => x.Id == 101);
var dev2 = list.FirstOrDefault(x => x.Id == 101);
//var dev1 = list.First(x => x.Id == 0); //报错
//var dev2 = list.FirstOrDefault(x => x.Id == 0);
//var dev1 = list.First(x => x.Id > 200);
//var dev2 = list.FirstOrDefault(x => x.Id > 200);
Console.WriteLine("\n单设备查找:");
Console.WriteLine($"ID: {dev1.Id}, 名称: {dev1.Name}, 结果: {dev1.Result}");
Console.WriteLine($"ID: {dev2.Id}, 名称: {dev2.Name}, 结果: {dev2.Result}");
Console.WriteLine("\n All方法测试");
var result = list.All(x => x.Result > 90);
Console.WriteLine($"result: {result}");
Console.WriteLine("\n Any方法测试");
var result2 = list.Any(x => x.Result > 90);
Console.WriteLine($"result: {result2}");
Console.WriteLine("\nCount方法示例");
var count = list.Count();
var count2 = list.Count(device => device.Type == "生产设备");
Console.WriteLine($"count: {count}");
Console.WriteLine($"count2: {count2}");
}
static bool ProductDevice(Device device)
{
return device.Type == "生产设备";
}
}
/// <summary>
/// 设备类
/// </summary>
class Device
{
/// <summary>
/// Id
/// </summary>
public int Id { get; set; }
/// <summary>
/// 设备类型
/// </summary>
public string Type { get; set; }
/// <summary>
/// 名称
/// </summary>
public string Name { get; set; }
/// <summary>
/// 测试结果
/// </summary>
public int Result { get; set; }
}