问题
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?
回答1:
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);
}
回答2:
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>
).
回答3:
First/FirstOrDefault with pick the first element in the sequence, nothing clever.
- FirstOrDefault
- First
来源:https://stackoverflow.com/questions/3700131/how-firstordefault-extension-method-works