我想知道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算法是否足够聪明,可以选择最佳算法,还是严格遵循这些算法中的任何一种算法?
答案 0 :(得分:8)
我查看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属性),它会尝试使用List。否则它使用枚举器。
编辑:谓词的另一个方法(我现在看到你正在谈论)并不是优化的,而是依赖于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);
}
答案 1 :(得分:1)
两者都没有,它使用枚举器只读取第一个值。当没有第一个值时,它返回null(或者更确切地说,是当前<T>
的默认值)。
答案 2 :(得分:0)
First / FirstOrDefault选择序列中的第一个元素,没什么好看的。