使用另一个函数的参数调用函数
Call function with a parameter from another function
我有一个函数重复调用另一个函数。
第二个函数有一个 bool 参数,可以改变它的行为方式,所以当我调用第一个函数时,我希望有一个参数来指定第二个函数的行为方式。
void Function1(int n, bool differentBehavior = false)
{
int a = Function2(n, differentBehavior);
int b = Function2(1, differentBehavior);
int c = Function2(2, differentBehavior);
return a + b + c;
}
int Function2(int x, bool differentBehavior)
{
if (!differentBehavior) // do something
else // do something else
}
代码本身显然是一个示例(实际上第二个函数被调用了 20 多次,为了代码的可读性,我希望不必每次都指定第二个参数),但我把它放在那里是为了解释什么我目前正在做。有没有更好的方法来实现这一目标?
你可以像这样引入一个局部函数来捕获第二个参数:
int Function1(int n, bool differentBehavior = false)
{
int func(int n) => Function2(n, differentBehavior);
int a = func(n);
int b = func(1);
int c = func(2);
return a + b + c;
}
这叫做“偏函数应用”。在这里查看更多:
https://codeblog.jonskeet.uk/2012/01/30/currying-vs-partial-function-application/
虽然 C# 不支持 true function Currying nor first-class partial function application,但您始终可以
使用一个新的局部作用域函数(又名局部函数)用预定义的参数包装你的Function2
......这在概念上是almost与部分应用程序相同,只是没有 referential-transparency 和笨拙的委托类型。
无论如何,如果你想将外部 Function1
的 differentBehavior
参数值传递给 Function2
那么你将需要使用一个闭包,它将捕获变量,但是this will introduce slight runtime performance complications:作为一个闭包,一般意味着一个GC堆分配和复制函数局部状态从堆栈到堆和yada yada。
但是,如果您只使用 constant 参数值 - 或者您可以为不同的预定义参数值使用不同的包装器,那么您可以使用 static
本地函数(需要 C# 8.0 或更高版本),防止您无意中创建闭包。
例如:
void Function1(int n, bool differentBehavior = false)
{
// Look ma, no closure!
static int PartiallyAppliedFunc2_False(int x) => Function2( x: x, differentBehavior: false );
static int PartiallyAppliedFunc2_True(int x) => Function2( x: x, differentBehavior: true );
int a = PartiallyAppliedFunc2_False(n);
int b = PartiallyAppliedFunc2_False(1);
int c = PartiallyAppliedFunc2_True(2);
return a + b + c;
}
int Function2(int x, bool differentBehavior)
{
if (!differentBehavior) // do something
else // do something else
}
当在堆栈上传递大量参数时,需要注意的一件事是是否存在某些 higher-level 状态可以由 class 的成员变量表示。
下面是最基本的状态机的一些代码。这种通用方法可能有助于解决您遇到的问题:
class Program
{
enum Behaviors
{
BehaviorA,
BehaviorB,
BehaviorC,
}
static Behaviors State { get; set; }
static void Main(string[] args)
{
for (State = Behaviors.BehaviorA; State <= Behaviors.BehaviorC; State++)
{
Console.WriteLine($"Function returned { Function1(0)}");
}
int Function1(int n)
{
int a = Function2(n);
int b = Function2(1);
int c = Function2(2);
return a + b + c;
}
int Function2(int x)
{
switch (State)
{
case Behaviors.BehaviorA:
return x * 10;
case Behaviors.BehaviorB:
return x * 20;
case Behaviors.BehaviorC:
return x * 30;
default:
throw new NotImplementedException();
}
}
}
}
我有一个函数重复调用另一个函数。
第二个函数有一个 bool 参数,可以改变它的行为方式,所以当我调用第一个函数时,我希望有一个参数来指定第二个函数的行为方式。
void Function1(int n, bool differentBehavior = false)
{
int a = Function2(n, differentBehavior);
int b = Function2(1, differentBehavior);
int c = Function2(2, differentBehavior);
return a + b + c;
}
int Function2(int x, bool differentBehavior)
{
if (!differentBehavior) // do something
else // do something else
}
代码本身显然是一个示例(实际上第二个函数被调用了 20 多次,为了代码的可读性,我希望不必每次都指定第二个参数),但我把它放在那里是为了解释什么我目前正在做。有没有更好的方法来实现这一目标?
你可以像这样引入一个局部函数来捕获第二个参数:
int Function1(int n, bool differentBehavior = false)
{
int func(int n) => Function2(n, differentBehavior);
int a = func(n);
int b = func(1);
int c = func(2);
return a + b + c;
}
这叫做“偏函数应用”。在这里查看更多:
https://codeblog.jonskeet.uk/2012/01/30/currying-vs-partial-function-application/
虽然 C# 不支持 true function Currying nor first-class partial function application,但您始终可以
使用一个新的局部作用域函数(又名局部函数)用预定义的参数包装你的Function2
......这在概念上是almost与部分应用程序相同,只是没有 referential-transparency 和笨拙的委托类型。
无论如何,如果你想将外部 Function1
的 differentBehavior
参数值传递给 Function2
那么你将需要使用一个闭包,它将捕获变量,但是this will introduce slight runtime performance complications:作为一个闭包,一般意味着一个GC堆分配和复制函数局部状态从堆栈到堆和yada yada。
但是,如果您只使用 constant 参数值 - 或者您可以为不同的预定义参数值使用不同的包装器,那么您可以使用 static
本地函数(需要 C# 8.0 或更高版本),防止您无意中创建闭包。
例如:
void Function1(int n, bool differentBehavior = false)
{
// Look ma, no closure!
static int PartiallyAppliedFunc2_False(int x) => Function2( x: x, differentBehavior: false );
static int PartiallyAppliedFunc2_True(int x) => Function2( x: x, differentBehavior: true );
int a = PartiallyAppliedFunc2_False(n);
int b = PartiallyAppliedFunc2_False(1);
int c = PartiallyAppliedFunc2_True(2);
return a + b + c;
}
int Function2(int x, bool differentBehavior)
{
if (!differentBehavior) // do something
else // do something else
}
当在堆栈上传递大量参数时,需要注意的一件事是是否存在某些 higher-level 状态可以由 class 的成员变量表示。
下面是最基本的状态机的一些代码。这种通用方法可能有助于解决您遇到的问题:
class Program
{
enum Behaviors
{
BehaviorA,
BehaviorB,
BehaviorC,
}
static Behaviors State { get; set; }
static void Main(string[] args)
{
for (State = Behaviors.BehaviorA; State <= Behaviors.BehaviorC; State++)
{
Console.WriteLine($"Function returned { Function1(0)}");
}
int Function1(int n)
{
int a = Function2(n);
int b = Function2(1);
int c = Function2(2);
return a + b + c;
}
int Function2(int x)
{
switch (State)
{
case Behaviors.BehaviorA:
return x * 10;
case Behaviors.BehaviorB:
return x * 20;
case Behaviors.BehaviorC:
return x * 30;
default:
throw new NotImplementedException();
}
}
}
}