我有一个为浮动下拉菜单生成一组选项的方法。该方法的类型为IEnumerable<FloatMenuOption>
。
当我将值作为List
返回时,它可以正常工作。但是当我逐一放弃它们时,每个项目都运行useAct
lambda,最后一个产生,尽管它们都有正确的标签。
任何人都可以解释为什么会这样吗?为什么要返回List
而不是逐个产生项目?
public override IEnumerable<FloatMenuOption> GetFloatMenuChoicesFor(Pawn myPawn)
{
List<FloatMenuOption> options = new List<FloatMenuOption>();
foreach ( Communicable commTarget in GetCommTargets() )
{
var localCommTarget = commTarget;
System.Action useAct = () =>
{
Job openJob = new Job();
openJob.commTarget = localCommTarget;
myPawn.MindHumanoid.TakeOrderedJob(openJob);
};
options.Add( new FloatMenuOption(localCommTarget.GetLabel(), useAct) );
}
return options;
//Simply commenting out the above line and uncommenting the two below causes the error
// foreach (var opt in options)
// yield return opt;
}
在任何一种情况下,选项都会出现正确的标签(来自localCommTarget.GetLabel()
)。但是,如果屈服了,它们都会为列表中的最后一项配置useAct lambda,而如果作为列表返回,它们每个都会执行自己的useAct lambda。
为什么?
答案 0 :(得分:1)
查看Captured variable in a loop in C#
我相信如果你将for循环更改为:
foreach (var opt in options)
{
var capturedOpt = opt;
yield return capturedOpt;
}
你会成为金色的。
答案 1 :(得分:0)
在您的实现中,如果您的代码生成结果而不是将它们添加到列表中,则仅使用localCommTarget的最后一个赋值。这样做的原因是lambda表达式的执行被推迟到对返回的实际访问。换句话说,不同的回报策略的执行顺序是不同的。