Find()vs. Where().FirstOrDefault()

Kin*_*tes 142 c# linq linq-to-objects

我经常看到人们使用Where.FirstOrDefault()搜索并抓住第一个元素.为什么不用Find()?对方是否有优势?我无法区分.

namespace LinqFindVsWhere
{
    class Program
    {
        static void Main(string[] args)
        {
            List<string> list = new List<string>();
            list.AddRange(new string[]
            {
                "item1",
                "item2",
                "item3",
                "item4"
            });

            string item2 = list.Find(x => x == "item2");
            Console.WriteLine(item2 == null ? "not found" : "found");
            string item3 = list.Where(x => x == "item3").FirstOrDefault();
            Console.WriteLine(item3 == null ? "not found" : "found");
            Console.ReadKey();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Ant*_*ram 190

在哪里Find上的方法IEnumerable<T>?(修辞问题.)

WhereFirstOrDefault方法可应用于对多种序列,包括List<T>,T[],Collection<T>,等等实现的任何序列IEnumerable<T>可以使用这些方法.Find仅适用于List<T>.通常更适用的方法更具有可重用性并且具有更大的影响.

我想我的下一个问题是他们为什么要添加查找.这是一个很好的提示.我唯一能想到的是FirstOrDefault可以返回除null之外的其他默认值.否则它似乎是一个毫无意义的补充

FindList<T>其他方法之前.List<T>在.NET 2.0中添加了泛型,并且Find是该类API的一部分.WhereFirstOrDefault添加为IEnumerable<T>Linq的扩展方法,Linq是后来的.NET版本.我不能肯定地说,如果Linq存在于Find将永远不会添加的2.0版本中,但对于早期.NET版本中的许多其他功能而言,可以说是这种情况,这些功能在以后的版本中已经过时或冗余.

  • 只是补充:没有必要调用Where和First或FirstOrDefault:First或FirstOrDefault允许您指定搜索谓词,使Where调用不必要 (75认同)
  • @Suncat2000 请提供一个例子 (8认同)
  • 但是`Where(condition).FirstOrDefault()`至少同样优化,有时甚至比`FirstOrDefault(condition)`更好.我们总是使用`Where()`来获得改进的性能. (3认同)
  • @Suncat2000 您使用 Linq 是因为它的表达能力并且想要编写声明性代码。您不应该担心这种微观改进,这些改进也可能在未来的实现中发生变化。另外,不要过早优化 (2认同)
  • @suncat2000我想验证该声明,因为如果它更快,那么firstordefault(predicate)就不会被实现为where(predicate).firstordefault()。 (2认同)

小智 45

我今天刚刚发现,在80K对象列表上做了一些测试,发现它Find()比使用Wherewith 快了1000%FirstOrDefault().直到每个人之前和之后测试一个计时器我都不知道.有时它是同一时间,否则它更快.

  • 你在Where AND FirstOrDefault尝试过吗?如果您这样做,或者只使用FirstOrDefault尝试它,看看Find()是否仍然更好. (6认同)
  • 听起来你没有用`.ToList()`或`.ToArray()`实现结果来实际执行查询. (5认同)
  • 这是因为`Find`使用了主键(因此索引),而`Where`是一个普通的sql查询 (3认同)
  • 从EF6开始,Find和FirstOrDefault都生成完全相同的SQL语句.您可以通过执行context.Database.Log = Console.Write在控制台应用程序中查看SQL.选址的示例是针对字符串列表使用内存中的"查找",而不是使用主键的DB.也许Find子句的语句转换 - 省略了对lambda表达式解析的需要,这是在这种情况下性能改进的原因.针对数据库我怀疑你会注意到RL情况的差异......我也想知道它是否使用Find先测试而不是第二次测试... (3认同)
  • 嗯,这种性能改进是因为 find() 在命中 DB 之前检查对象的缓存,而 where() 总是去 DB 获取对象 (2认同)

pen*_*tur 29

Find只有实现List<T>,而Where().FirstOrDefault()所有的作品IEnumerable<T>.


Cha*_*lky 29

如果数据源是实体框架,则会有一个非常重要的区别: Find将发现处于"已添加"状态且尚未持久化但未实现的实体Where.这是设计的.

  • 问题中的“Find”方法与 EF 的“Find”方法没有任何关系。 (3认同)