有什么不同?

在集合上使用Linq,以下几行代码有什么不同?

if(!coll.Any(i => i.Value))

if(!coll.Exists(i => i.Value))

更新1

当我拆解。 .Exists它看起来像没有代码。

更新2

任何人都知道为什么这里没有代码?


请参阅文档

List.Exists(对象方法 - MSDN)

确定List(T)是否包含与由指定的谓词定义的条件相匹配的元素。

这是从.NET 2.0开始的,所以在LINQ之前。 意味着与Predicate 委托一起使用,但是lambda表达式是向后兼容的。 此外,只有List有这个(甚至没有IList)

IEnumerable.Any(扩展方法 - MSDN)

确定序列的任何元素是否满足条件。

这在.NET 3.5中是新的,并且使用Func(TSource,bool)作为参数,所以这是为了与lambda表达式和LINQ一起使用。

在行为中,这些是相同的。


区别在于Any是System.Linq.Enumerable上定义的任何IEnumerable<T>的扩展方法。 它可以用于任何IEnumerable<T>实例。

存在似乎不是一种扩展方法。 我的猜测是coll是List<T>类型。 如果是这样的话Exists是一个与Any非常相似的实例方法。

总之 ,这些方法基本上是相同的。 一个比另一个更普遍。

  • 任何也有一个重载,它不接受任何参数,只是查找枚举中的任何项。
  • 存在没有这样的过载。

  • TLDR; 性能方面Any似乎都比较慢 (如果我已经正确设置了这个值,几乎同时评估两个值)

            var list1 = Generate(1000000);
            var forceListEval = list1.SingleOrDefault(o => o == "0123456789012");
            if (forceListEval != "sdsdf")
            {
                var s = string.Empty;
                var start2 = DateTime.Now;
                if (!list1.Exists(o => o == "0123456789012"))
                {
                    var end2 = DateTime.Now;
                    s += " Exists: " + end2.Subtract(start2);
                }
    
                var start1 = DateTime.Now;
                if (!list1.Any(o => o == "0123456789012"))
                {
                    var end1 = DateTime.Now;
                    s +=" Any: " +end1.Subtract(start1);
                }
    
                if (!s.Contains("sdfsd"))
                {
    
                }
    

    测试列表生成器:

    private List<string> Generate(int count)
        {
            var list = new List<string>();
            for (int i = 0; i < count; i++)
            {
                list.Add( new string(
                Enumerable.Repeat("ABCDEFGHIJKLMNOPQRSTUVWXYZ", 13)
                    .Select(s =>
                    {
                        var cryptoResult = new byte[4];
                        new RNGCryptoServiceProvider().GetBytes(cryptoResult);
                        return s[new Random(BitConverter.ToInt32(cryptoResult, 0)).Next(s.Length)];
                    })
                    .ToArray())); 
            }
    
            return list;
        }
    

    拥有10M记录

    “任何:00:00:00.3770377存在:00:00:00.2490249”

    有5M记录

    “任何时间:00:00:00.0940094 Exists:00:00:00.1420142”

    拥有1M记录

    “任何:00:00:00.0180018存在:00:00:00.0090009”

    有了500k,(我也翻过了评估的顺序,看看是否没有其他操作与先运行相关。)

    “Exists:00:00:00.0050005 Any:00:00:00.0100010”

    拥有10万条记录

    “Exists:00:00:00.0010001 Any:00:00:00.0020002”

    看起来Any情况都会减慢2。

    编辑:对于5和10M记录,我改变了它生成列表的方式, Exists突然变得比Any更慢,这意味着我正在测试的方式有问题。

    新的测试机制:

    private static IEnumerable<string> Generate(int count)
        {
            var cripto = new RNGCryptoServiceProvider();
            Func<string> getString = () => new string(
                Enumerable.Repeat("ABCDEFGHIJKLMNOPQRSTUVWXYZ", 13)
                    .Select(s =>
                    {
                        var cryptoResult = new byte[4];
                        cripto.GetBytes(cryptoResult);
                        return s[new Random(BitConverter.ToInt32(cryptoResult, 0)).Next(s.Length)];
                    })
                    .ToArray());
    
            var list = new ConcurrentBag<string>();
            var x = Parallel.For(0, count, o => list.Add(getString()));
            return list;
        }
    
        private static void Test()
        {
            var list = Generate(10000000);
            var list1 = list.ToList();
            var forceListEval = list1.SingleOrDefault(o => o == "0123456789012");
            if (forceListEval != "sdsdf")
            {
                var s = string.Empty;
    
                var start1 = DateTime.Now;
                if (!list1.Any(o => o == "0123456789012"))
                {
                    var end1 = DateTime.Now;
                    s += " Any: " + end1.Subtract(start1);
                }
    
                var start2 = DateTime.Now;
                if (!list1.Exists(o => o == "0123456789012"))
                {
                    var end2 = DateTime.Now;
                    s += " Exists: " + end2.Subtract(start2);
                }
    
                if (!s.Contains("sdfsd"))
                {
    
                }
            }
    

    编辑2:好吧,以消除生成测试数据的任何影响我把它全部写入文件,现在从那里读取它。

     private static void Test()
        {
            var list1 = File.ReadAllLines("test.txt").Take(500000).ToList();
            var forceListEval = list1.SingleOrDefault(o => o == "0123456789012");
            if (forceListEval != "sdsdf")
            {
                var s = string.Empty;
                var start1 = DateTime.Now;
                if (!list1.Any(o => o == "0123456789012"))
                {
                    var end1 = DateTime.Now;
                    s += " Any: " + end1.Subtract(start1);
                }
    
                var start2 = DateTime.Now;
                if (!list1.Exists(o => o == "0123456789012"))
                {
                    var end2 = DateTime.Now;
                    s += " Exists: " + end2.Subtract(start2);
                }
    
                if (!s.Contains("sdfsd"))
                {
                }
            }
        }
    

    10M

    “任何:00:00:00.1640164存在:00:00:00.0750075”

    5M

    “任何:00:00:00.0810081存在:00:00:00.0360036”

    1M

    “任何:00:00:00.0190019存在:00:00:00.0070007”

    500K

    “任何:00:00:00.0120012存在:00:00:00.0040004”

    在这里输入图像描述

    链接地址: http://www.djcxy.com/p/52941.html

    上一篇: What's the difference?

    下一篇: What's the next big thing after LINQ?