查找()与FirstOrDefault的)性能( [英] Performance of Find() vs. FirstOrDefault()

查看:259
本文介绍了查找()与FirstOrDefault的)性能(的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

可能重复:
  查找()与凡()。FirstorDefault()

得到了一个有趣的结果,具有单一字符串属性的简单引用类型的大序列中寻找戴安娜。

Got an interesting outcome searching for Diana within a large sequence of a simple reference type having a single string property.

Stopwatch watch = new Stopwatch();        
string diana = "Diana";

while (Console.ReadKey().Key != ConsoleKey.Escape)
{
    //Armour with 1000k++ customers. Wow, should be a product with a great success! :)
    var customers = (from i in Enumerable.Range(0, 1000000)
                     select new Customer
                     {
                        Name = Guid.NewGuid().ToString()
                     }).ToList();

    customers.Insert(999000, new Customer { Name = diana }); // Putting Diana at the end :)

    //1. System.Linq.Enumerable.DefaultOrFirst()
    watch.Restart();
    customers.FirstOrDefault(c => c.Name == diana);
    watch.Stop();
    Console.WriteLine("Diana was found in {0} ms with System.Linq.Enumerable.FirstOrDefault().", watch.ElapsedMilliseconds);

    //2. System.Collections.Generic.List<T>.Find()
    watch.Restart();
    customers.Find(c => c.Name == diana);
    watch.Stop();
    Console.WriteLine("Diana was found in {0} ms with System.Collections.Generic.List<T>.Find().", watch.ElapsedMilliseconds);
}

是不是因为在List.Find(不枚举的开销这一点)或本加,也许别的东西?

Is this because of no Enumerator overhead in List.Find() or this plus maybe something else?

查找()运行几乎是两倍快,希望的的球队不会标记它在未来过时。

Find() runs almost as twice as faster, hoping .Net team will not mark it Obsolete in the future.

推荐答案

我能模仿你的结果,所以我反编译你的程序和存在的的差异查找 FirstOrDefault

I was able to mimic your results so I decompiled your program and there is a difference between Find and FirstOrDefault.

首先这里是反编译程序。我做你的数据对象的anonmyous数据项只是编译

First off here is the decompiled program. I made your data object an anonmyous data item just for compilation

    List<\u003C\u003Ef__AnonymousType0<string>> source = Enumerable.ToList(Enumerable.Select(Enumerable.Range(0, 1000000), i =>
    {
      var local_0 = new
      {
        Name = Guid.NewGuid().ToString()
      };
      return local_0;
    }));
    source.Insert(999000, new
    {
      Name = diana
    });
    stopwatch.Restart();
    Enumerable.FirstOrDefault(source, c => c.Name == diana);
    stopwatch.Stop();
    Console.WriteLine("Diana was found in {0} ms with System.Linq.Enumerable.FirstOrDefault().", (object) stopwatch.ElapsedMilliseconds);
    stopwatch.Restart();
    source.Find(c => c.Name == diana);
    stopwatch.Stop();
    Console.WriteLine("Diana was found in {0} ms with System.Collections.Generic.List<T>.Find().", (object) stopwatch.ElapsedMilliseconds);

这里要注意的关键一点是, FirstOrDefault 上称为可枚举,而查找被称为源列表上的一个方法。

The key thing to notice here is that FirstOrDefault is called on Enumerable whereas Find is called as a method on the source list.

那么,什么是找做什么?这是在反编译查找方法

So, what is find doing? This is the decompiled Find method

private T[] _items;

[__DynamicallyInvokable]
public T Find(Predicate<T> match)
{
  if (match == null)
    ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
  for (int index = 0; index < this._size; ++index)
  {
    if (match(this._items[index]))
      return this._items[index];
  }
  return default (T);
}

所以它的迭代项目的数组这是有道理的,因为列表是一个阵列上的包装。

So it's iterating over an array of items which makes sense, since a list is a wrapper on an array.

不过, FirstOrDefault ,在可枚举类,使用的foreach 迭代的项目。它使用一个迭代器列表,朝旁边。我想,你所看到的是迭代的开销

However, FirstOrDefault, on the Enumerable class, uses foreach to iterate the items. This uses an iterator to the list and move next. I think what you are seeing is the overhead of the iterator

[__DynamicallyInvokable]
public static TSource FirstOrDefault<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
  if (source == null)
    throw Error.ArgumentNull("source");
  if (predicate == null)
    throw Error.ArgumentNull("predicate");
  foreach (TSource source1 in source)
  {
    if (predicate(source1))
      return source1;
  }
  return default (TSource);
}

的Foreach只是<一href="http://stackoverflow.com/questions/5816776/in-c-is-foreach-purely-a-syntactic-sugar-or-is-there-anything-deeper-about">syntatic糖关于使用枚举模式。看看这个图片

Foreach is just syntatic sugar on using the enumerable pattern. Look at this image

.

我点击的foreach,看看它在做什么,你可以看到dotpeek要带我去枚举/电流/下一实现这是有道理的。

I clicked on foreach to see what it's doing and you can see dotpeek wants to take me to the enumerator/current/next implementations which makes sense.

除此之外,他们基本上是相同的(测试传入的predicate,看一个项目是你想要的)

Other than that they are basically the same (testing the passed in predicate to see if an item is what you want)

这篇关于查找()与FirstOrDefault的)性能(的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆