C#中的匿名方法可以自己调用吗?

我有以下代码:

class myClass { private delegate string myDelegate(Object bj); protected void method() { myDelegate build = delegate(Object bj) { var letters= string.Empty; if (someCondition) return build(some_obj); //This line seems to choke the compiler else string.Empty; }; ...... } } 

有没有另外一种方法来build立一个匿名方法在C#中,以便它可以调用自己?

你可以把它分解成两个语句,并使用捕获variables的魔法来实现recursion效果:

 myDelegate build = null; build = delegate(Object bj) { var letters= string.Empty; if (someCondition) return build(some_obj); else string.Empty; }; 

如果你正在创build一个recursion函数,我build议避免匿名代表。 只要创build一个方法,并让它自己recursion调用。

匿名方法的意思是匿名 – 你不应该通过名字(非匿名)来调用它们。

匿名recursion在C#中有关于这个话题的极好的讨论。

recursion是美丽的,lambda是最终的抽象。 但是他们怎么能一起使用呢? Lambdas是匿名函数,recursion需要名字…

由于这再次popup,这里是一个使用Y-combinator的例子:

 // 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; } 

这是一个使用它来调用匿名,recursion函数…

 Func<int,int> exp = Y<int,int>( e => x => ( x <=1 ) ? 1 : x * e( x - 1 ) ); Console.WriteLine( exp(5) ); 

你会注意到,如果你不使用Y-combinator并设置只有委托recursion,你不会得到正确的recursion。 例如 …

 // 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是我们期望的(4+1=5)将值递增1,但badRecCopy现在实际上是返回值的平方(5*( (5+1)-1 ) ,我们几乎可以肯定没有期望。

如果使用Y-combinator,它将按预期工作。

 Func<int,int> goodRec = Y<int,int>( exp => x => ( x <=1 ) ? 1 : x * exp( x - 1 ) ); Func<int,int> goodRecCopy = goodRec; 

你得到你所期望的。

 goodRec = x => x + 1; Console.WriteLine( goodRec(4) ); Console.WriteLine( goodRecCopy(5) ); // Output // 5 // 120 

您可以阅读更多关于Y-combinator (PDF链接)。

由于匿名方法的主体是variables本身的初始化,因此不能在build内部调用build 。 您正在尝试在定义之前使用variables。

不是我推荐这个(因为在这里创build一个真正的方法是recursion的会简单),但如果你有兴趣,你可以阅读匿名recursion在C#中 :

recursion是美丽的,lambda是最终的抽象。 但是他们怎么能一起使用呢? Lambdas是匿名函数,recursion需要名称。

如果你使用Y ,你的函数成为函数本身的一个参数,所以你可以recursion地调用它:

 class myClass { private delegate string myDelegate(Object bj); protected void method() { myDelegate build = delegate(Object obj) { // f is the function itself, which is passed into the function return Functional.Y<Object, string>(f => bj => { var letters = string.Empty; if (someCondition) return f(some_obj); // use f else return string.Empty; })(obj); }; } } public static class Functional { public delegate Func<A, R> Recursive<A, R>(Recursive<A, R> r); public static Func<A, R> Y<A, R>(Func<Func<A, R>, Func<A, R>> f) { Recursive<A, R> rec = r => a => f(r(r))(a); return rec(rec); } } 

如果您正在使用recursion匿名方法,您可能需要将其提升为class级中普通的私人方法。