Я посмотрел в Отражатель :
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);
}
Он пытается сделать это с помощью List, если коллекция может быть приведена как 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);
}