C# Linq延迟查询的执行实例代码
作者:沉默♪☞小傲 时间:2023-04-24 05:34:59
C# Linq延迟查询
在定义linq查询表达式时,查询是不会执行,查询会在迭代数据项时运行。它使用yield return 语句返回谓词为true的元素。
var names = new List<string> { "Nino", "Alberto", "Juan", "Mike", "Phil" };
var namesWithJ = from n in names
where n.StartsWith("J")
orderby n
select n;
Console.WriteLine("First iteration");
foreach (string name in namesWithJ)
{
Console.WriteLine(name);
}
Console.WriteLine();
names.Add("John");
names.Add("Jim");
names.Add("Jack");
names.Add("Denny");
Console.WriteLine("Second iteration");
foreach (string name in namesWithJ)
{
Console.WriteLine(name);
}
运行结果为
First iteration
JuanSecond iteration
Jack
Jim
John
Juan
从执行结果可以看出,当在定义namesWithJ时并不会执行,而是在执行每个foreach语句时进行,所以后面增加的“John”、“Jim”、“Jack”和“Denny”在第二次迭代时也会参与进来。
ToArray()、ToList()等方法可以改变这个操作,把namesWithJ的定义语句修改为
var namesWithJ = (from n in names
where n.StartsWith("J")
orderby n
select n).ToList();
运行结果为
First iteration
JuanSecond iteration
Juan
在日常工作中,我们常会使用 datas.Where(x=>x.XX == XXX).FirstOrDefault() 和 datas.FirstOrDefault(x=>x.XX == XXX),其实这两种写法性能是等效的,如果真的要在性能上分个高低,请见下面
C# Linq.FirstOrDefault、Linq.Where、Linq.AsParallel、List.Exists、List.Find、Dictionar.TryGetValue、HashSet.Contains 性能的比较
今天我们来比较一下集合检索方法性能更优问题,测试代码
public class Entity
{
public int Id { get; set; }
public int No { get; set; }
public string Col1 { get; set; }
public string Col2 { get; set; }
public string Col3 { get; set; }
public string Col4 { get; set; }
public string Col5 { get; set; }
public string Col6 { get; set; }
public string Col7 { get; set; }
public string Col8 { get; set; }
public string Col9 { get; set; }
public string Col10 { get; set; }
}
static void TestFindVelocity(int totalDataCount, int executeCount)
{
#region 构造数据
List<Entity> datas = new List<Entity>();
for (int i = 0; i < totalDataCount; i++)
{
var item = new Entity
{
No = i + 1,
Col1 = Guid.NewGuid().ToString("N"),
Col2 = Guid.NewGuid().ToString("N"),
Col3 = Guid.NewGuid().ToString("N"),
Col4 = Guid.NewGuid().ToString("N"),
Col5 = Guid.NewGuid().ToString("N"),
Col6 = Guid.NewGuid().ToString("N"),
Col7 = Guid.NewGuid().ToString("N"),
Col8 = Guid.NewGuid().ToString("N"),
Col9 = Guid.NewGuid().ToString("N"),
Col10 = Guid.NewGuid().ToString("N"),
};
datas.Add(item);
}
#endregion
var dicDatas = datas.ToDictionary(x => x.No);
var hashSetDatas = datas.ConvertAll<Tuple<int, int>>(x => new Tuple<int, int>(x.No, x.No + 1000)).ToHashSet();
Stopwatch sw = new Stopwatch();
Random random = new Random();
Entity searchResult = null;
bool searchResultBool = false;
// 每次查询索引
List<int> indexs = Enumerable.Range(1, executeCount).Select(x => random.Next(1, totalDataCount)).ToList();
sw.Start();
for (int i = 0; i < executeCount; i++)
{
searchResult = datas.FirstOrDefault(x => x.No == indexs[i]);
}
sw.Stop();
Console.WriteLine($"list FirstOrDefault 耗时:{sw.ElapsedMilliseconds}");
sw.Restart();
for (int i = 0; i < executeCount; i++)
{
searchResult = datas.Where(x => x.No == indexs[i]).First();
}
sw.Stop();
Console.WriteLine($"list Where+First 耗时:{sw.ElapsedMilliseconds}");
sw.Restart();
for (int i = 0; i < executeCount; i++)
{
searchResultBool = datas.Exists(x => x.No == indexs[i]);
}
sw.Stop();
Console.WriteLine($"list Exist 耗时:{sw.ElapsedMilliseconds}");
sw.Restart();
for (int i = 0; i < executeCount; i++)
{
searchResult = datas.Find(x => x.No == indexs[i]);
}
sw.Stop();
Console.WriteLine($"list Find 耗时:{sw.ElapsedMilliseconds}");
sw.Restart();
for (int i = 0; i < executeCount; i++)
{
dicDatas.TryGetValue(indexs[i], out searchResult);
}
sw.Stop();
Console.WriteLine($"dictionary TryGetValue 耗时:{sw.ElapsedMilliseconds}");
sw.Restart();
for (int i = 0; i < executeCount; i++)
{
searchResultBool = hashSetDatas.Contains(new Tuple<int, int>(indexs[i], indexs[i] + 1000));
}
sw.Stop();
Console.WriteLine($"Hashset contains 耗时:{sw.ElapsedMilliseconds}");
}
结果
(集合数量,测试次数) | Linq.FirstOrDefault | Linq.Where+First | List.Exists | List.Find | Dictionary.TryGetValue | HashSet.Contains |
(100, 5000000) | 4544 | 3521 | 1992 | 1872 | 66 | 924 |
(1000, 5000000) | 41751 | 29417 | 20631 | 19490 | 70 | 869 |
(10000, 5000000) | 466918 | 397425 | 276409 | 281647 | 85 | 946 |
(50000, 5000) | 6292 | 4602 | 4252 | 3559 | 0 | 2 |
(500000, 5000) | 56988 | 55568 | 48423 | 48395 | 1 | 5 |
应避免错误写法是 datas.Where(x=>x.XX == XXX).ToList()[0]
。
来源:https://www.cnblogs.com/Cxiaoao/p/14674744.html
![](/images/zang.png)
![](/images/jiucuo.png)
猜你喜欢
详解Java变量与常量
![](https://img.aspxhome.com/file/2023/5/59005_0s.png)
Android HttpClient GET或者POST请求基本使用方法
Kotlin基础学习之lambda中return语句详解
Android Data Binding数据绑定详解
![](https://img.aspxhome.com/file/2023/3/137543_0s.png)
maven install报错中程序包xxx不存在的问题解决
![](https://img.aspxhome.com/file/2023/9/65309_0s.jpg)
Android实现象棋游戏
Java8中的 Lambda表达式教程
C# using的本质及使用详解
![](https://img.aspxhome.com/file/2023/0/76390_0s.png)
springboot项目打成war包部署到tomcat遇到的一些问题
C#学习笔记之状态模式详解
![](https://img.aspxhome.com/file/2023/0/122710_0s.png)
Spring学习之Bean的装配多种方法
springboot如何引入外部yml配置文件
![](https://img.aspxhome.com/file/2023/5/104055_0s.png)
使用java实现BBS论坛发送邮件过程详解
![](https://img.aspxhome.com/file/2023/3/65763_0s.png)
Android实现退出时关闭所有Activity的方法
Spring Boot配置线程池拒绝策略的场景分析(妥善处理好溢出的任务)
c#实现简单控制台udp异步通信程序示例
Java编程GUI中的事件绑定代码示例
关于SpringBoot3.x中spring.factories功能被移除的解决方案
![](https://img.aspxhome.com/file/2023/8/95038_0s.png)
Android开发中的9个常见错误和解决方法
flutter中使用流式布局示例详解
![](https://img.aspxhome.com/file/2023/5/86765_0s.jpg)