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
Juan

Second 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
Juan

Second 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.FirstOrDefaultLinq.Where+FirstList.ExistsList.FindDictionary.TryGetValueHashSet.Contains

(100, 5000000)

454435211992187266924

(1000, 5000000)

4175129417206311949070869

(10000, 5000000)

46691839742527640928164785946

(50000, 5000)

629246024252355902

(500000, 5000)

5698855568484234839515

应避免错误写法是 datas.Where(x=>x.XX == XXX).ToList()[0]

来源:https://www.cnblogs.com/Cxiaoao/p/14674744.html

标签:linq,延迟,查询
0
投稿

猜你喜欢

  • 详解Java变量与常量

    2023-11-09 21:00:14
  • Android HttpClient GET或者POST请求基本使用方法

    2021-11-18 04:26:57
  • Kotlin基础学习之lambda中return语句详解

    2023-09-04 16:33:41
  • Android Data Binding数据绑定详解

    2023-05-07 14:54:39
  • maven install报错中程序包xxx不存在的问题解决

    2023-03-05 03:06:51
  • Android实现象棋游戏

    2021-10-23 02:32:15
  • Java8中的 Lambda表达式教程

    2023-10-13 01:32:29
  • C# using的本质及使用详解

    2022-10-10 06:11:23
  • springboot项目打成war包部署到tomcat遇到的一些问题

    2023-10-12 12:46:46
  • C#学习笔记之状态模式详解

    2021-09-15 21:56:08
  • Spring学习之Bean的装配多种方法

    2023-09-04 09:32:36
  • springboot如何引入外部yml配置文件

    2023-11-07 07:35:38
  • 使用java实现BBS论坛发送邮件过程详解

    2022-12-19 16:58:30
  • Android实现退出时关闭所有Activity的方法

    2021-10-03 00:15:00
  • Spring Boot配置线程池拒绝策略的场景分析(妥善处理好溢出的任务)

    2022-08-05 07:12:24
  • c#实现简单控制台udp异步通信程序示例

    2022-06-13 18:54:38
  • Java编程GUI中的事件绑定代码示例

    2023-02-04 17:36:01
  • 关于SpringBoot3.x中spring.factories功能被移除的解决方案

    2022-03-25 03:04:33
  • Android开发中的9个常见错误和解决方法

    2023-08-26 16:12:35
  • flutter中使用流式布局示例详解

    2023-08-24 23:49:06
  • asp之家 软件编程 m.aspxhome.com