Sé que esto puede sonar extraño, pero ni siquiera sé cómo buscar esta sintaxis en Internet y tampoco estoy seguro de qué significa exactamente.
Así que miré un poco de código MoreLINQ y luego noté este método
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;
}
}
}
¿Qué es esta extraña declaración de devolución? return _();
?
return _(); IEnumerable<TSource> _()
:?return _(); IEnumerable<TSource> _()
que alyield return
?return _(); IEnumerable<TSource> _()
. Podría confundirse por la forma en que se ve en lugar de la declaración de devolución real.Respuestas:
Este es C # 7.0 que admite funciones locales ...
C # actual con
Func<T>
El truco es que _ () se declara después de que se usa, lo cual está perfectamente bien.
Uso práctico de funciones locales
El ejemplo anterior es solo una demostración de cómo se puede usar el método en línea, pero lo más probable es que si va a invocar el método solo una vez, entonces no sirve de nada.
Pero en el ejemplo anterior, como se mencionó en los comentarios de Phoshi y Luaan , existe la ventaja de usar la función local. Dado que la función con retorno de rendimiento no se ejecutará a menos que alguien la repita, en este caso se ejecutará el método fuera de la función local y se realizará la validación del parámetro incluso si nadie iterará el valor.
Muchas veces hemos repetido código en el método, veamos este ejemplo.
Podría optimizar esto con ...
fuente
_AnonymousFunction
o simplemente_
, mientras que esperaría que una función anónima genuina sea algo así(x,y) => x+y
. Yo llamaría a esto una función local, pero no estoy acostumbrado a la terminología de C #.yield return
, no se ejecuta ningún código hasta que el enumerable se enumera realmente. Esto no es deseable, ya que desea, por ejemplo, verificar los argumentos de inmediato. La única forma de hacer esto en C # es separando el método en dos métodos: uno conyield return
s y el otro sin. Los métodos en línea le permiten declarar elyield
método using en su interior , evitando el desorden y el posible uso indebido de un método que es estrictamente interno a su padre y no reutilizable.Considere el ejemplo más simple
_()
es una función local declarada dentro del método que contiene la declaración de retorno.fuente