public virtual void OnRegistrationJoin(RegistrationJoinEventArgs e)
{
foreach (Mobile member in e.Team)
{
member.SendMessage(1161, "You join the {0}.", EventFullName);
if (e.Team.Count > 1)
{
Joinees.Remove(member);
member.SendMessage(1161, "Your team formation is:");
int i = 0;
foreach (Mobile parter in e.Team.Where(partner => partner != member).ToList())
{
member.SendMessage(1150, "{0}: {1}.", ++i, partner.Name);
}
}
}
Members.Add(e.Team);
}
我通过resharper获得“访问修改后的闭包”警告,我想知道这段代码有什么问题,因为我在内循环中所做的只是发送消息?
答案 0 :(得分:13)
问题在于:
e.Team.Where(partner => partner != member)
变量member
是对外部范围中member
变量的直接引用。虽然您在上面的代码中可能没有遇到此问题,但是当您在多个线程上运行代码或者您没有立即在Where
方法中评估lambda时(例如,使用IQueryable
代替IEnumerable
)。
这是一个问题的原因是C#生成一个方法然后作为委托传递给Where
。该方法需要直接访问memeber
。如果您要将引用分配给另一个变量,如下所示:
var m = member;
// ...
e.Team.Where(partner => partner != m);
然后C#可以在一个名为“closure”的构造中“捕获”该值,并将其传递给生成的方法。这将确保在member
更改时,您将其传递给Where
时所期望的值不会更改。
答案 1 :(得分:2)
部分resharper抱怨的是e.Team.Where(partner => partner != member).ToList()
,因为引用的member
会被更改。在这种情况下,这不是问题,但在其他情况下,这可能是一个问题。
注意:您不必使用ToList()
,这会强制评估IEnumerable<T>
。只需迭代e.Team.Where(partner => partner != member)
。
答案 2 :(得分:0)
我认为member.SendMessage
可以修改member
那是修改lambda中使用的闭合变量