在集合上使用LINQ,下面几行代码之间的区别是什么?
if(!coll.Any(i => i.Value))
and
if(!coll.Exists(i => i.Value))
更新1
当我解汇编。exists时,它看起来好像没有代码。
更新2
有人知道为什么这里没有代码吗?
在集合上使用LINQ,下面几行代码之间的区别是什么?
if(!coll.Any(i => i.Value))
and
if(!coll.Exists(i => i.Value))
更新1
当我解汇编。exists时,它看起来好像没有代码。
更新2
有人知道为什么这里没有代码吗?
当前回答
当你修正测量值时——如上所述:Any和Exists,加上平均值——我们会得到以下输出:
Executing search Exists() 1000 times ...
Average Exists(): 35566,023
Fastest Exists() execution: 32226
Executing search Any() 1000 times ...
Average Any(): 58852,435
Fastest Any() execution: 52269 ticks
Benchmark finished. Press any key.
其他回答
当你修正测量值时——如上所述:Any和Exists,加上平均值——我们会得到以下输出:
Executing search Exists() 1000 times ...
Average Exists(): 35566,023
Fastest Exists() execution: 32226
Executing search Any() 1000 times ...
Average Any(): 58852,435
Fastest Any() execution: 52269 ticks
Benchmark finished. Press any key.
看文档
列表。存在(对象方法- MSDN)
确定List(T)是否包含与指定谓词定义的条件匹配的元素。
它从。net 2.0就存在了,所以在LINQ之前。应该与Predicate委托一起使用,但lambda表达式向后兼容。还有,List有这个(甚至不是IList)
IEnumerable。Any(扩展方式- MSDN)
确定序列的任何元素是否满足条件。
这是. net 3.5中的新功能,并使用Func(TSource, bool)作为参数,因此这是用于lambda表达式和LINQ的。
在行为上,它们是相同的。
此外,这只在Value为bool类型时才有效。通常这与谓词一起使用。任何谓词通常用于查找是否有满足给定条件的元素。这里你只是在做一个从元素i到bool属性的映射。它将搜索Value属性为true的“i”。一旦完成,该方法将返回true。
区别在于Any是System.Linq.Enumerable上定义的任何IEnumerable<T>的扩展方法。它可以用于任何IEnumerable<T>实例。
Exists似乎不是一种扩展方法。我猜coll的类型是List<T>。Exists是一个实例方法,它的功能非常类似于Any。
简而言之,方法本质上是相同的。一个比另一个更普遍。
Any也有一个重载,它不接受参数,只是在枚举项中查找任何项。 Exists没有这样的过载。
作为Matas关于基准测试的回答的延续。
TL/DR: Exists()和Any()同样快。
首先:使用Stopwatch进行基准测试并不精确(参见series0one关于另一个不同但相似的主题的回答),但它比DateTime精确得多。
获得真正精确读数的方法是使用性能分析。但是有一种方法可以了解这两个方法的性能如何相互衡量,那就是执行两个方法大量的时间,然后比较每个方法的最快执行时间。这样一来,JITing和其他噪音给我们带来糟糕的读数就无关紧要了(确实如此),因为在某种意义上,两次执行都“同样具有误导性”。
static void Main(string[] args)
{
Console.WriteLine("Generating list...");
List<string> list = GenerateTestList(1000000);
var s = string.Empty;
Stopwatch sw;
Stopwatch sw2;
List<long> existsTimes = new List<long>();
List<long> anyTimes = new List<long>();
Console.WriteLine("Executing...");
for (int j = 0; j < 1000; j++)
{
sw = Stopwatch.StartNew();
if (!list.Exists(o => o == "0123456789012"))
{
sw.Stop();
existsTimes.Add(sw.ElapsedTicks);
}
}
for (int j = 0; j < 1000; j++)
{
sw2 = Stopwatch.StartNew();
if (!list.Exists(o => o == "0123456789012"))
{
sw2.Stop();
anyTimes.Add(sw2.ElapsedTicks);
}
}
long existsFastest = existsTimes.Min();
long anyFastest = anyTimes.Min();
Console.WriteLine(string.Format("Fastest Exists() execution: {0} ticks\nFastest Any() execution: {1} ticks", existsFastest.ToString(), anyFastest.ToString()));
Console.WriteLine("Benchmark finished. Press any key.");
Console.ReadKey();
}
public static List<string> GenerateTestList(int count)
{
var list = new List<string>();
for (int i = 0; i < count; i++)
{
Random r = new Random();
int it = r.Next(0, 100);
list.Add(new string('s', it));
}
return list;
}
在执行上述代码4次之后(依次在包含1 000 000个元素的列表上执行1 000 Exists()和Any()),不难看出这些方法几乎同样快。
Fastest Exists() execution: 57881 ticks
Fastest Any() execution: 58272 ticks
Fastest Exists() execution: 58133 ticks
Fastest Any() execution: 58063 ticks
Fastest Exists() execution: 58482 ticks
Fastest Any() execution: 58982 ticks
Fastest Exists() execution: 57121 ticks
Fastest Any() execution: 57317 ticks
有一点细微的差别,但这个差别太小了,不能用背景噪音来解释。我的猜测是,如果用10,000或100,000 Exists()和Any()来代替,那么这个微小的差异将或多或少地消失。