Sono un po 'curioso di sapere quale sia considerata "migliore pratica" quando si tratta di FirstOrDefault.FirstOrDefault() off di un LINQ rispetto a FirstOrDefault() con un Lambda?
Ho già visto questa domanda, che è simile alla domanda che ho, ma non abbastanza vicino da rispondere alla mia domanda.
Quale di questi è "codice migliore"? e perché?
var foos = GetMyEnumerableFoos();
var foo1 = (from f in foos
where f.Bar == "spider monkey"
select f).FirstOrDefault();
/* OR */
var foo2 = foos.FirstOrDefault(f => f.Bar == "spider monkey");
tendo verso quest'ultima, come IMO, rende il codice più pulito. Ma sono curioso di sapere se il "coraggio" tecnico di ciò che sta accadendo è più efficiente nell'altro senso. Questo cambia se stai usando diversi tipi di oggetti IEnumerables? come DataTables o array di stringhe o oggetti LINQ?
========= modificare ==========
Supponendo post di Jon Skeet è corretta, sono andato a cercare in Reflector per vedere cosa Dove e FirstOrDefault simile, e ecco quello che mi si avvicinò con:
Nel caso di foos.Where (f => f.Bar == "scimmia ragno") FirstOrDefault()
public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
if (source == null)
{
throw Error.ArgumentNull("source");
}
if (predicate == null)
{
throw Error.ArgumentNull("predicate");
}
if (source is Iterator<TSource>)
{
return ((Iterator<TSource>) source).Where(predicate);
}
if (source is TSource[])
{
return new WhereArrayIterator<TSource>((TSource[]) source, predicate);
}
if (source is List<TSource>)
{
return new WhereListIterator<TSource>((List<TSource>) source, predicate);
}
return new WhereEnumerableIterator<TSource>(source, predicate);
}
che confluiranno in.:
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);
}
Nel caso di foos.FirstOrDefault (f => f.Bar == "spider monkey");
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);
}
Guardando che ancora mi lascia un po 'confuso, ci sarebbe efficienze aggiunti dai utilizzando l'iteratore adeguata per alcuni tipi di oggetto? O è più efficiente saltare tutto ciò e iniziare semplicemente il ciclo e il test? Il mio istinto mi dice di nuovo che è quest'ultimo.
Questo è interessante. Ho fatto un po 'più di scavo dopo che sei stato pubblicato solo per vedere cosa sta succedendo in quei tre metodi che hai citato. Ho pubblicato i miei risultati sopra ... Certamente aiuta a rispondere alla mia domanda. –
Non ho controllato, ma presumo che nessuno dei 'Dove'' restituisce 's in un' IList', quindi i due loop finali sono effettivamente gli stessi: il 'MoveNext' chiamerà il' predicato' dal 'Dove ', dove la chiamata' FirstOrDefault (predicate) 'la chiama esplicitamente. Quindi la versione 'Where' ha una chiamata extra per' false' (e il predicato '' true', se presente) finale'. –