He encontrado este código aquí :
public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey>? comparer) { if (source == null) throw new ArgumentNullException(nameof(source)); if (keySelector == null) throw new ArgumentNullException(nameof(keySelector)); return _(); IEnumerable<TSource> _() { var knownKeys = new HashSet<TKey>(comparer); foreach (var element in source) { if (knownKeys.Add(keySelector(element))) yield return element; } } }
Al principio no entendí esta parte return _(); IEnumerable<TSource> _()
, pero me di cuenta de que es una función local llamada y declarada en la misma línea. Se hizo aquí .
Mi pregunta es: ¿hay alguna ventaja sobre simplemente insertar ese código?
public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey>? comparer) { if (source == null) throw new ArgumentNullException(nameof(source)); if (keySelector == null) throw new ArgumentNullException(nameof(keySelector)); var knownKeys = new HashSet<TKey>(comparer); foreach (var element in source) { if (knownKeys.Add(keySelector(element))) yield return element; } }
Diría que la versión actual es más detallada y tiene más sangría, entonces, ¿cuál es la ventaja? ¿Es solo cuestión de gustos?
La versión con el método local se lanzará inmediatamente si source
o keySelector
es nulo, porque no está implementado con un bloque iterador.
La versión "en línea" usa un bloque iterador, por lo que nada del código, incluida la validación, se ejecutará hasta que el código de llamada comience a iterar sobre el IEnumerable<TSource>
.
En general, la validación entusiasta hace que sea más fácil detectar y comprender los errores: el seguimiento de la pila es más claro y no hay demora entre "hacer la llamada rota" y "ver la falla".
El mismo enfoque también se puede usar para escribir métodos de devolución de tareas que fallan con entusiasmo: escriba un método de devolución de tareas "regular" que llame a un método local asíncrono después de realizar la validación.