First()和Find()之间的区别
所以我知道Find()
只是一个List<T>
方法,而First()
是任何IEnumerable<T>
的扩展。 我也知道如果没有parameter passing, First()
会返回第一个元素,而Find()
会抛出一个exception。 最后,我知道如果找不到元素, First()
将抛出exception,而Find()
将返回该types的默认值。
我希望能澄清我实际上在问什么。 这是一个计算机科学问题,在计算层面处理这些方法。 我已经明白, IEnumerable<T>
扩展并不总是如人们所期望的那样运行。 所以这里是Q,我的意思是从“接近金属”的angular度来看: 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);
First()
和Find()
如何在上面的代码中发现它们的值之间有什么实际的计算差异?
注意:现在让我们忽略像AsParallel()
和AsQueryable()
这样的东西。
这是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); }
这里是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(); }
所以这两种方法的工作方式大致相同:迭代所有项目,直到find与谓词相匹配的项目。 唯一明显的区别是Find
使用for
循环,因为它已经知道元素的数量,而First
使用foreach循环,因为它不知道它。
First
会发现一个exception,但它找不到任何东西,然而FirstOrDefault
和Find
完全一样(除了它是如何遍历元素的)。
由于List<>
没有以任何方式编入索引,所以必须通过所有的值才能find一个特定的值。 因此,与通过枚举(除了创build一个可枚举的帮助程序对象实例之外)遍历列表相比,它没有什么区别。
这就是说,请记住Find
函数的创build方式比第First
扩展方法(Framework V2.0 vs V3.5)早,我怀疑如果List<>
类已经实现了同时作为扩展方法。
如果在枚举器而不是列表上使用Find,将会有潜在的性能成本,因为枚举器可能不需要获取整个列表来满足谓词呢? 相反,如果你已经有一个列表,然后查找会更好。
顺便说一句Find相当于FirstOrDefault()
不是First()
。 因为如果First()
谓词不满足任何列表元素,你将会得到一个exception。 在这里,返回一个dotpeek ,另一个伟大的免费reflection器replace一些ReSharperfunction
这里为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(); }
这里是List <>。Find:
/// <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); }