Это забавно, потому что это - то, что я сказал, когда я увидел веб-формы в первый раз.
Вы можете разбить его на два оператора и использовать магию захваченных переменных для достижения эффекта рекурсии:
myDelegate build = null;
build = delegate(Object bj)
{
var letters= string.Empty;
if (someCondition)
return build(some_obj);
else string.Empty;
};
Если вы создаете рекурсивную функцию, я бы рекомендовал избегать анонимных делегатов. Просто создайте метод и пусть он будет вызывать себя рекурсивно.
Анонимные методы должны быть анонимными - вы не должны вызывать их по имени (не анонимно).
Если вы дошли до рекурсивных анонимных методов, вы можете сделать их обычным частным методом в вашем классе.
Анонимная рекурсия в C # имеет потрясающее обсуждение этой темы.
Рекурсия прекрасна, а лямбды высшая абстракция. Но как можно их можно использовать вместе? Лямбды анонимные функции и рекурсия требует имен ...
Поскольку это снова появилось, вот пример использования Y-комбинатора:
// This is the combinator
public static Func<A,R> Y<A,R>( Func<Func<A,R>, Func<A,R>> f )
{
Func<A,R> g = null;
g = f( a => g(a) );
return g;
}
Вот его использование для вызова анонимной рекурсивной функции ...
Func<int,int> exp = Y<int,int>( e => x => ( x <=1 ) ? 1 : x * e( x - 1 ) );
Console.WriteLine( exp(5) );
Вы заметите, что если вы не используете Y-комбинатор и настраиваете рекурсию только с делегатом, вы не получите правильную рекурсию. Например ...
// This is BAD. Do not do this!
Func<int,int> badRec = null;
badRec = x => ( x <= 1 ) ? 1 : x * badRec( x - 1 );
Но все работает нормально ...
Console.WriteLine( badRec(5) );
// Output
// 120
А вот попробуйте ...
Func<int,int> badRec = null;
badRec = x => ( x <= 1 ) ? 1 : x * badRec( x - 1 );
Func<int,int> badRecCopy = badRec;
badRec = x => x + 1;
Console.WriteLine( badRec(4) );
Console.WriteLine( badRecCopy(5) );
// Output
// 5
// 25
Что?!?
Видите, после строки badRec = x => x + 1;
, на самом деле у вас есть делегат ...
badRecCopy = x => ( x <= 1 ) ? 1 : x * ( (x+1)-1 );
Итак, badRec увеличивает значение на 1, которое мы ожидаем (4 + 1 = 5)
, но badRecCopy теперь фактически возвращает квадрат значения (5 * ((5 + 1) -1)
, которого мы почти наверняка не ожидали.
Если вы используете Y-комбинатор, он будет работать, как ожидалось .. .
Func<int,int> goodRec = Y<int,int>( exp => x => ( x <=1 ) ? 1 : x * exp( x - 1 ) );
Func<int,int> goodRecCopy = goodRec;
И вы получите то, что ожидаете.
Вы не можете вызвать build
внутри самой build
, поскольку тело анонимного метода - это инициализация самой переменной. Вы пытаетесь использовать переменную до того, как она будет определена.
Не то, чтобы я рекомендовал это (поскольку было бы намного проще создать здесь реальный метод, который является рекурсивным), но если вам интересно, вы можете прочтите Анонимная рекурсия в C # :
Рекурсия прекрасна, а лямбды высшая абстракция. Но как можно их можно использовать вместе? Лямбды анонимные функции и рекурсия требует имен.