Ter*_*ryP 4 c# lambda encapsulation anonymous-function
我正在研究一种需要在不同位置重复一个小操作的方法,但要重复的代码应该是该方法的私有代码.显而易见的解决方案是嵌套函数.无论我尝试什么,C#编译器对我来说都是barfs.
大致等于这个Perl片段的东西:
my $method = sub {
$helper_func = sub { code to encapsulate };
# more code
&$helper( called whenever needed );
# more code
}
Run Code Online (Sandbox Code Playgroud)
正是我在谈论的,以及我在C#中想要实现的目标.
类中没有其他方法应该能够在此上下文中访问辅助函数.在C#中编写这个构造的最合理的方法,就像在我看来会是这样的:
var helper = (/* parameter names */) => { /* code to encapsulate */ };
Run Code Online (Sandbox Code Playgroud)
实际上让编译器获得了保持.
由于这样的赋值是被禁止的,因为使用较旧的delegate(){}语法代替lambda,因此在方法中声明一个委托类型 - 然而csc实际上允许我写的是,这是:
private delegate /* return type */ Helper(/* parameters */);
private /* return type */ method(/* parameters */) {
Helper helper = (/* parameter names */) => {
/* code to encapsulate */
};
// more code
helper( /* called whenever needed */ );
// more code
}
Run Code Online (Sandbox Code Playgroud)
对于不复制和粘贴一大堆代码并手动编辑参数这一切都很好,但是它会将私有委托类型泄漏给类的其余部分而不是将其保密.这首先打败了目的.对参数使用goto语句和局部变量可以在此上下文中更好地封装"helper",而不会牺牲代码重用.如果我想通过寄存器传递参数来模拟函数调用,我想宁愿使用汇编程序.我没有找到一种可接受的重构代码的方法来完全避免这个问题.
那么,甚至可以强制这种面向公共对象的语言服从吗?
你实际上可以在C#中做到这一点.
Func<T1, T2, ..., TReturn> myFunc = (a, b, ...) =>
{
//code that return type TReturn
};
Run Code Online (Sandbox Code Playgroud)
如果需要匿名方法返回类型void使用Action而不是Func:
Action<T1, T2, ...> myAction = (a, b, ...) =>
{
//code that doesn't return anything
};
Run Code Online (Sandbox Code Playgroud)
如果你在C#3.5或更高版本,你可以利用lambdas和便利委托声明Func<>和Action<>.所以举个例子
void DoSomething()
{
Func<int,int> addOne = (ii) => ii +1;
var two = addOne(1);
}
Run Code Online (Sandbox Code Playgroud)
你不能做的原因
var addOne = (ii) => ii +1;
Run Code Online (Sandbox Code Playgroud)
因为Homoiconicity,lambda可以被解释为两个不同的结构,一个委托和一个表达式树.因此需要在声明中明确.