输出变量和嵌套的 lambda
Out variables and nested lambdas
编码只是为了找点乐趣,让我的头脑了解匿名方法等。我有一个 class,其主要目的是 运行 循环中的 lambda。 lambda 有一个输出参数(exit),它被传递回 class。现在我可以按照下面的代码嵌套它们,其中 l2 在 l1 的 lambda 中声明。
int outer = 0;
Loop l1 = new Loop().Infinite((out bool outerExit) =>
{
int inner = 0;
outer++;
Loop l2 = new Loop().Infinite((out bool innerExit) =>
{
inner++;
Debug.WriteLine($"{outer}-{inner}");
innerExit = inner >= 3;
outerExit = inner >= 3;
});
//outerExit = outer >= 3;
});
Assert.Equal(3, outer);
然而,这会在我为 outerExit 赋值的 l2 lambda 中产生错误。
Error CS1628 Cannot use ref, out, or in parameter 'outerExit' inside
an anonymous method, lambda expression, query expression, or local
function
想法是在满足特定条件时从内部循环中退出两个循环。
对于那些感兴趣的人。
public class Loop
{
//this is a delegate TYPE!!! that matches our function
public delegate void ExitableAction<T1>(out T1 a);
//in thiscase it is a bool
protected ExitableAction<bool> action;
protected LoopType type;
public Loop Infinite(ExitableAction<bool> actn)
{
action = actn;
type = LoopType.Infinite;
Start();
return this;
}
protected void Start()
{
bool exit = false;
while(!exit)
{
action.Invoke(out exit);
}
}
}
关于为什么你不能使用ref
/out
参数,参见this post。
您似乎想重新创建一个具有“中断”功能的“循环”语句。您可以使用另一个 Action<bool>
委托代替 out
参数来实现 break
语句。
public class Loop
{
protected Action<Action<bool>> action;
public Loop Infinite(Action<Action<bool>> actn)
{
action = actn;
Start();
return this;
}
protected void Start()
{
bool exit = false;
while (!exit)
{
// passes the Action<bool> that assigns the given bool to exit
action((b) => exit = b);
}
}
}
int outer = 0;
Loop l1 = new Loop().Infinite(setOuterExit =>
{
int inner = 0;
outer++;
Loop l2 = new Loop().Infinite(setInnerExit =>
{
inner++;
Console.WriteLine($"{outer}-{inner}");
setInnerExit(inner >= 3);
setOuterExit(inner >= 3);
});
setOuterExit(outer >= 3);
});
这给出了最终的 outer
值 3。但是如果你想要那个,你可以只删除内部循环中的 setOuterExit
调用 - 它也给出 3 作为输出。
现在,内部 setOuterExit
调用分配给 exit
的值正在被外部 setOuterExit
调用“覆盖”,因此外部循环不会立即中断它击中了内部 setOuterExit
。我们可以将 exit
的赋值更改为:
action((b) => exit |= b);
因此,如果 exit
被设置为 true
,则没有其他值可以覆盖它。这将解决这个问题,但请注意 setOuterExit
仍然不会像真正的 break;
语句那样工作。 setOuterExit
之后的代码仍然会被执行,例如
编码只是为了找点乐趣,让我的头脑了解匿名方法等。我有一个 class,其主要目的是 运行 循环中的 lambda。 lambda 有一个输出参数(exit),它被传递回 class。现在我可以按照下面的代码嵌套它们,其中 l2 在 l1 的 lambda 中声明。
int outer = 0;
Loop l1 = new Loop().Infinite((out bool outerExit) =>
{
int inner = 0;
outer++;
Loop l2 = new Loop().Infinite((out bool innerExit) =>
{
inner++;
Debug.WriteLine($"{outer}-{inner}");
innerExit = inner >= 3;
outerExit = inner >= 3;
});
//outerExit = outer >= 3;
});
Assert.Equal(3, outer);
然而,这会在我为 outerExit 赋值的 l2 lambda 中产生错误。
Error CS1628 Cannot use ref, out, or in parameter 'outerExit' inside an anonymous method, lambda expression, query expression, or local function
想法是在满足特定条件时从内部循环中退出两个循环。
对于那些感兴趣的人。
public class Loop
{
//this is a delegate TYPE!!! that matches our function
public delegate void ExitableAction<T1>(out T1 a);
//in thiscase it is a bool
protected ExitableAction<bool> action;
protected LoopType type;
public Loop Infinite(ExitableAction<bool> actn)
{
action = actn;
type = LoopType.Infinite;
Start();
return this;
}
protected void Start()
{
bool exit = false;
while(!exit)
{
action.Invoke(out exit);
}
}
}
关于为什么你不能使用ref
/out
参数,参见this post。
您似乎想重新创建一个具有“中断”功能的“循环”语句。您可以使用另一个 Action<bool>
委托代替 out
参数来实现 break
语句。
public class Loop
{
protected Action<Action<bool>> action;
public Loop Infinite(Action<Action<bool>> actn)
{
action = actn;
Start();
return this;
}
protected void Start()
{
bool exit = false;
while (!exit)
{
// passes the Action<bool> that assigns the given bool to exit
action((b) => exit = b);
}
}
}
int outer = 0;
Loop l1 = new Loop().Infinite(setOuterExit =>
{
int inner = 0;
outer++;
Loop l2 = new Loop().Infinite(setInnerExit =>
{
inner++;
Console.WriteLine($"{outer}-{inner}");
setInnerExit(inner >= 3);
setOuterExit(inner >= 3);
});
setOuterExit(outer >= 3);
});
这给出了最终的 outer
值 3。但是如果你想要那个,你可以只删除内部循环中的 setOuterExit
调用 - 它也给出 3 作为输出。
现在,内部 setOuterExit
调用分配给 exit
的值正在被外部 setOuterExit
调用“覆盖”,因此外部循环不会立即中断它击中了内部 setOuterExit
。我们可以将 exit
的赋值更改为:
action((b) => exit |= b);
因此,如果 exit
被设置为 true
,则没有其他值可以覆盖它。这将解决这个问题,但请注意 setOuterExit
仍然不会像真正的 break;
语句那样工作。 setOuterExit
之后的代码仍然会被执行,例如