Может анонимный метод в C# называть себя?

Это забавно, потому что это - то, что я сказал, когда я увидел веб-формы в первый раз.

53
задан Matt 30 July 2009 в 08:12
поделиться

5 ответов

Вы можете разбить его на два оператора и использовать магию захваченных переменных для достижения эффекта рекурсии:

myDelegate build = null;
build = delegate(Object bj)
        {
           var letters= string.Empty;
           if (someCondition)
               return build(some_obj);                            
           else string.Empty;
        };
92
ответ дан 7 November 2019 в 08:20
поделиться

Если вы создаете рекурсивную функцию, я бы рекомендовал избегать анонимных делегатов. Просто создайте метод и пусть он будет вызывать себя рекурсивно.

Анонимные методы должны быть анонимными - вы не должны вызывать их по имени (не анонимно).

30
ответ дан 7 November 2019 в 08:20
поделиться

Если вы дошли до рекурсивных анонимных методов, вы можете сделать их обычным частным методом в вашем классе.

1
ответ дан 7 November 2019 в 08:20
поделиться

Анонимная рекурсия в 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;

И вы получите то, что ожидаете.

24
ответ дан 7 November 2019 в 08:20
поделиться

Вы не можете вызвать build внутри самой build , поскольку тело анонимного метода - это инициализация самой переменной. Вы пытаетесь использовать переменную до того, как она будет определена.

Не то, чтобы я рекомендовал это (поскольку было бы намного проще создать здесь реальный метод, который является рекурсивным), но если вам интересно, вы можете прочтите Анонимная рекурсия в C # :

Рекурсия прекрасна, а лямбды высшая абстракция. Но как можно их можно использовать вместе? Лямбды анонимные функции и рекурсия требует имен.

10
ответ дан 7 November 2019 в 08:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: