软件编程
位置:首页>> 软件编程>> C#编程>> C# Linq延迟查询的执行实例代码

C# Linq延迟查询的执行实例代码

作者:沉默♪☞小傲  发布时间:2023-04-24 05:34:59 

标签:linq,延迟,查询

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

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com