PRI*_*UFF 6 .net c# linq closures
采用以下代码,Resharper告诉我voicesSoFar并voicesNeededMaximum导致"访问修改后的闭包".我读到了这些,但令我困惑的是Resharper建议通过在LINQ查询之前提取变量来解决这个问题.但这就是他们已经到了的地方!
如果我只是增加ReSharper的停止抱怨int voicesSoFar1 = voicesSoFar之后int voicesSoFar = 0.是否有一些我不理解的奇怪逻辑使得Resharper的建议正确无误?或者有没有办法安全地"访问修改后的闭包"在这样的情况下,而不会导致错误?
// this takes voters while we have less than 300 voices
int voicesSoFar = 0;
int voicesNeededMaximum = 300;
var eligibleVoters =
voters.TakeWhile((p => (voicesSoFar += p.Voices) < voicesNeededMaximum));
Run Code Online (Sandbox Code Playgroud)
你将一个外部变量变为lambda表达式会产生一个非常讨厌的问题.问题是这样的:如果你尝试迭代eligibleVoters两次(foreach(var voter in eligibleVoters) { Console.WriteLine(voter.Name); }并且紧跟在(foreach(var voter in eligibleVoters) { Console.WriteLine(voter.Name); })之后你将看不到相同的输出.从功能编程的角度来看,这是不正确的.
这是一个扩展方法,它将累积,直到累加器上的某些条件为真:
public static IEnumerable<T> TakeWhileAccumulator<T, TAccumulate>(
this IEnumerable<T> elements,
TAccumulate seed,
Func<TAccumulate, T, TAccumulate> accumulator,
Func<TAccumulate, bool> predicate
) {
TAccumulate accumulate = seed;
foreach(T element in elements) {
if(!predicate(accumulate)) {
yield break;
}
accumulate = accumulator(accumulate, element);
yield return element;
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
var eligibleVoters = voters.TakeWhileAccumulator(
0,
(votes, p) => votes + p.Voices,
i => i < 300
);
Run Code Online (Sandbox Code Playgroud)
因此,上述说累积声音,而我们累积不到300票.
然后用:
foreach (var item in eligibleVoters) { Console.WriteLine(item.Name); }
Console.WriteLine();
foreach (var item in eligibleVoters) { Console.WriteLine(item.Name); }
Run Code Online (Sandbox Code Playgroud)
输出是:
Alice
Bob
Catherine
Alice
Bob
Catherine
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
817 次 |
| 最近记录: |