Здравствуйте, nt2000, Вы писали:
N>правильно ли я понял: функцию вместе с её телом нельзя передавать в параметре (только её заголовок), а вот если её наименование поменять на секретное наименование, то становится возможным передавать в параметре вместе с заголовком и её тело,даже если оно и не существует нигде ?
Нет, неправильно.
Обычные функции имеют имя, по которому к ним обращаются. У них есть и "заголовок", и тело.
Заголовок в данном случае — это сигнатура, которая описывает, что функция принимает, а что — возвращает.
Сигнатуру саму по себе никуда "передать" нельзя.
Давать функции имя нужно в двух случаях:
1. Когда мы хотим использовать её много раз
2. Когда мы хотим задокументировать её назначение.
Вот простой пример:
public static bool IsEven(int i) => { i % 2 == 0;}
....
var even = from n in numbers where IsEven(n) select n;
Здесь мы определили функцию по имени IsEven. Её сигнатура — Func<int, bool>. Её тело —
{return i % 2 == 0;}.
В нашем коде эта функция нужна ровно один раз; поэтому замусоривать ею пространство имён — не очень хорошо.
Поэтому мы можем её никак не называть — можно сконструировать её прямо по месту использования:
var even = from n in numbers where n % 2 == 0 select n;
Здесь плохо видно, где заканчивается where и где начинается функция, поэтому можно задать её чуть более явно (по-прежнему оставив её без имени):
var even = numbers.Where((int n)=>{n % 2 == 0});
Тело вполне себе существует; "секретное наименование" тут неважно — это просто подкапотная реализация семантики, заданной спецификацией.
Просто язык позволяет разделить имя функции и ссылку на неё.
То есть мы можем делать в любом порядке — сначала сконструировать именованную функцию, а потом взять на неё ссылку и передать туда, где ждут ссылку на функцию:
var even = numbers.Where(IsEven); // это функция из первого примера
А можем сначала сконструировать функцию, а потом дать имя ссылке на неё:
Func<int, bool> isEven = (n)=>{n % 2 == 0}); // справа - анонимная функция, слева - именованная переменная типа "делегат"
var even = numbers.Where(isEven);
Особенность тут — в том, что без анонимности любой код обязан быть членом класса. То есть можно писать методы, можно — аксессоры свойств, а вот для "просто кусок кода с параметрами" в хардкорных ОО-языках конструкций нету.
Конструкции типа linq во многом опираются на такие вот простые кирпичики без повторной используемости, заставлять программиста выписывать отдльно все декларации всех участвующих "кусков кода" — оверкилл. Код теряет читаемость.
Вот для её сохранения и приделали анонимные функции в C#.