FirstOrDefault 扩展方法如何工作?

发布于 2024-09-18 12:03:33 字数 566 浏览 8 评论 0原文

我想知道 FirstOrDefault 扩展方法如何工作?它遵循以下哪一种算法?

使用:

var arr = new[] {1, 2, 3, 4, 5, 6, 7};
return arr.FirstOrDefault(x => x%2 == 0);

算法 1:

for(int i = 0; i < arr.Length; i++)
{
   if(arr[i] % 2 == 0)
     return arr[i];
}
return 0;

算法 2:

var list = new List<int>();
for(int i = 0; i < arr.Length; i++)
{
   if(arr[i] % 2 == 0)
     list.Add(arr[i]);
}
return list.Count == 0 ? 0 : list[0];

FirstOrDefault 算法是否足够智能,可以选择最佳算法,还是严格遵循这些算法中的任何一种?

I was wondering on how FirstOrDefault extension method works? Which one of the following algorithms does it follows?

Use:

var arr = new[] {1, 2, 3, 4, 5, 6, 7};
return arr.FirstOrDefault(x => x%2 == 0);

Algorithm 1:

for(int i = 0; i < arr.Length; i++)
{
   if(arr[i] % 2 == 0)
     return arr[i];
}
return 0;

Algorithm 2:

var list = new List<int>();
for(int i = 0; i < arr.Length; i++)
{
   if(arr[i] % 2 == 0)
     list.Add(arr[i]);
}
return list.Count == 0 ? 0 : list[0];

Does the FirstOrDefault algorithm is smart enough to choose the optimal one or it strictly follow any one of these algorithms?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

我查看了 Reflector

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(并实现 Count 属性)。否则它使用枚举器。

编辑:带有谓词的另一种方法(我现在看到你正在谈论)没有那么优化,并且依赖于 IEnumerable 接口来执行 foreach 而不是 IList。

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

I looked in Reflector:

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

It tries to do it with a List if the collection can be cast as IList (and implements the Count property). Otherwise it uses the Enumerator.

EDIT: The other method with the predicate (which I now see you are talking about) is not as optimised and relies on the IEnumerable interface to perform a foreach rather than IList.

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 local in source)
    {
        if (predicate(local))
        {
            return local;
        }
    }
    return default(TSource);
}
苏佲洛 2024-09-25 12:03:33

First/FirstOrDefault 选择序列中的第一个元素,没什么聪明的。

First/FirstOrDefault with pick the first element in the sequence, nothing clever.

白馒头 2024-09-25 12:03:33

两者都不是,它使用枚举器仅读取第一个值。当没有第一个值时,它返回 null(或者更确切地说,当前 的默认值)。

Neither, it uses an enumerator to read only the very first value. When there is no first value, it returns null (or rather, the default value for the current <T>).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文