C#First()和Find()之间的区别

Squ*_*ama 52 c# linq list c#-4.0

所以我知道这Find()只是一种List<T>方法,而First()对任何方法都是一种扩展IEnumerable<T>.我也知道,First()如果没有传递参数,将返回第一个元素,而Find()抛出异常.最后,我知道First()如果找不到元素会抛出异常,而Find()返回类型的默认值.

我希望能够解决我实际要问的问题.这是一个计算机科学问题,并在计算层面处理这些方法.我已经明白,IEnumerable<T>扩展并不总是像人们期望的那样运行.所以这是Q,我的意思是从"接近金属"的角度来看:Find()和之间的区别是什么First()

这里有一些代码可以为这个问题提供基本的假设.

var l = new List<int> { 1, 2, 3, 4, 5 };
var x = l.First(i => i == 3);
var y = l.Find(i => i == 3);
Run Code Online (Sandbox Code Playgroud)

在上面的代码中如何First()Find()发现它们的值之间是否有任何实际的计算差异?

注:让我们忽略的东西AsParallel()AsQueryable()现在.

Tho*_*que 56

这是List<T>.Find(来自Reflector)的代码:

public T Find(Predicate<T> match)
{
    if (match == null)
    {
        ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
    }
    for (int i = 0; i < this._size; i++)
    {
        if (match(this._items[i]))
        {
            return this._items[i];
        }
    }
    return default(T);
}
Run Code Online (Sandbox Code Playgroud)

这是Enumerable.First:

public static TSource First<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 local in source)
    {
        if (predicate(local))
        {
            return local;
        }
    }
    throw Error.NoMatch();
}
Run Code Online (Sandbox Code Playgroud)

因此,两种方法的工作方式大致相同:它们迭代所有项目,直到找到与谓词匹配的项目.唯一明显的区别是Find使用for循环,因为它已经知道元素的数量,并First使用foreach循环,因为它不知道它.

  • 它是一个.NET反汇编程序,你可以从Redgate免费获得它:http://www.red-gate.com/products/reflector/.Pro版本不是免费的,但它允许您单步执行框架或第三方程序集的代码. (4认同)
  • @pcnThird,很久以前Reflector停止了自由,但有几个免费替代品.查看JustDecompile(Telerik),dotPeek(Jetbrains)或ILSpy(开源) (4认同)
  • 接受的答案是错误的.'唯一明显的区别是'如果找不到匹配,则First()抛出异常,而Find()返回默认值(在大多数情况下为null).这意味着如果使用Find并获取null,则不知道它是否意味着"找不到匹配"或"在序列中找到空元素". (4认同)
  • 什么是这个反射器,我该如何获得它? (2认同)
  • @synek317 原发帖者提到他们已经知道异常引发的差异,并且更担心实际查找代码本身是如何工作的。在这种情况下,我认为这个答案是正确的。 (2认同)

Dog*_*ett 19

First当它什么也没找到时会抛出一个异常,FirstOrDefault但是它会完全相同Find(除了它如何迭代元素).


pyt*_*kaa 5

BTW Find等于而FirstOrDefault()不是First()。因为如果谓词of First()不满足任何列表元素,那么您将获得异常。这就是返回dotpeek的地方,这是ReSharper的一些功能的另一个免费的免费反射器替代

这里的Enumerable.First(...)Enumerable.FirstOrDefault(...)扩展方法:

    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 element in source) { 
            if (predicate(element)) return element;
        } 
        return default(TSource); 
    }


    public static TSource First<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 element in source) {
            if (predicate(element)) return element; 
        }
        throw Error.NoMatch();
    }
Run Code Online (Sandbox Code Playgroud)

这是用于List <>。查找:

/// <summary>
/// Searches for an element that matches the conditions defined by the specified predicate, and returns the first occurrence within the entire <see cref="T:System.Collections.Generic.List`1"/>.
/// </summary>
/// 
/// <returns>
/// The first element that matches the conditions defined by the specified predicate, if found; otherwise, the default value for type <paramref name="T"/>.
/// </returns>
/// <param name="match">The <see cref="T:System.Predicate`1"/> delegate that defines the conditions of the element to search for.</param><exception cref="T:System.ArgumentNullException"><paramref name="match"/> is null.</exception>
[__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);
}
Run Code Online (Sandbox Code Playgroud)


小智 5

1 - Find()返回Null如果实体不在范围内,但First()会抛出异常
2- Find()已添加到上下文,但尚未保存到数据库返回的实体