Wiem, że może to brzmieć dziwnie, ale nie wiem nawet, jak przeszukać tę składnię w Internecie, a także nie jestem pewien, co dokładnie oznacza.
Więc obejrzałem trochę kodu MoreLINQ, a potem zauważyłem tę metodę
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;
}
}
}
Co to za dziwne polecenie zwrotu? return _();
?
return _(); IEnumerable<TSource> _()
:?return _(); IEnumerable<TSource> _()
niżyield return
?return _(); IEnumerable<TSource> _()
. Mógłby być zdezorientowany wyglądem, a nie faktyczną deklaracją zwrotu.Odpowiedzi:
To jest C # 7.0, który obsługuje funkcje lokalne ...
Bieżący C # z
Func<T>
Sztuczka polega na tym, że _ () jest deklarowane po jej użyciu, co jest całkowicie w porządku.
Praktyczne wykorzystanie funkcji lokalnych
Powyższy przykład to tylko demonstracja, w jaki sposób można użyć metody inline, ale najprawdopodobniej jeśli zamierzasz wywołać metodę tylko raz, to nie będzie to przydatne.
Ale w powyższym przykładzie, jak wspomniano w komentarzach Phoshi i Luaan , istnieje zaleta korzystania z funkcji lokalnej. Ponieważ funkcja z yield return nie zostanie wykonana, chyba że ktoś ją iteruje, w tym przypadku zostanie wykonana metoda poza funkcją lokalną, a walidacja parametrów zostanie wykonana, nawet jeśli nikt nie będzie iterował wartości.
Wiele razy powtarzaliśmy kod w metodzie, spójrzmy na ten przykład.
Mógłbym to zoptymalizować za pomocą ...
źródło
_AnonymousFunction
lub po prostu_
, podczas gdy spodziewałbym się, że prawdziwa anonimowa funkcja będzie czymś podobnym(x,y) => x+y
. Nazwałbym to funkcją lokalną, ale nie jestem przyzwyczajony do terminologii C #.yield return
, żaden kod nie jest wykonywany, dopóki nie zostanie wyliczony. Jest to niepożądane, ponieważ chcesz np. Od razu zweryfikować argumenty. Jedynym sposobem, aby to zrobić w C #, jest rozdzielenie metody na dwie metody - jedną zyield return
s, a drugą bez. Metody wbudowane pozwalają zadeklarowaćyield
metodę using wewnątrz , unikając bałaganu i potencjalnego niewłaściwego użycia metody, która jest ściśle wewnętrzna dla jej rodzica i nie nadaje się do ponownego użycia.Rozważmy prostszy przykład
_()
jest funkcją lokalną zadeklarowaną w metodzie zawierającej instrukcję return.źródło