1

我尝试在 MSDN、SO 和 Web 上搜索,但找不到答案。

假设我有一个收藏品FirstOrDefault()。假设它找到了该项目。它是停止并返回项目还是继续搜索并妨碍性能?

4

4 回答 4

7

如果您对此仍然含糊不清,.NET 框架中的源代码是从这里实现的:

public static TSource FirstOrDefault<TSource>(this IEnumerable<TSource> source) {
    if (source == null) throw Error.ArgumentNull("source");
    IList<TSource> list = source as IList<TSource>;
    if (list != null) {
        if (list.Count > 0) return list[0];
    }
    else {
        using (IEnumerator<TSource> e = source.GetEnumerator()) {
            if (e.MoveNext()) return e.Current;
        }
    }
    return default(TSource);
}

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);
}

显然,如果成立,它将停止

于 2013-05-15T06:36:26.283 回答
1

FirstOrDefault将迭代直到找到元素,并且只有在找不到元素时才需要迭代整个元素IEnumerable

于 2013-05-15T06:35:25.933 回答
1

它停止并返回。

这是相关的反编译代码(对于FirstOrDefault()FirstOrDefault(predicate)

[__DynamicallyInvokable]
public static TSource FirstOrDefault<TSource>(this IEnumerable<TSource> source)
{
  if (source == null)
    throw Error.ArgumentNull("source");
  IList<TSource> list = source as IList<TSource>;
  if (list != null)
  {
    if (list.Count > 0)
      return list[0];
  }
  else
  {
    using (IEnumerator<TSource> enumerator = source.GetEnumerator())
    {
      if (enumerator.MoveNext())
        return enumerator.Current;
    }
  }
  return default (TSource);
}

这里它所做的是检查它是否实现IList,如果实现,则返回第一项,如果有的话。如果没有,它会获取一个枚举器并尝试执行MoveNext. 如果成功,则返回Enumerator.Current. 否则它只返回类型的默认值 ( TSource)

[__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);
}

在这里,它首先检查所有 args are not null,然后 foreaches 直到找到与谓词匹配的项目,然后返回它。如果没有,那么它只返回该类型的默认值。

(如果您想知道如何获取源代码,我使用了 dotPeek。这是一个很棒的工具!)

于 2013-05-15T06:36:14.853 回答
0

我希望它确实如此..但这里有几种方法可以告诉你:

  1. 测试一下。做一个大集合(这需要很长时间才能搜索),然后将要查找的元素放在开头,然后放在结尾。这两个测试所用的时间应该不同,第一个应该更短。

  2. 查看.Net 源代码,然后自己看看。

于 2013-05-15T06:35:09.477 回答