Adi*_*rda 22 c# scope anonymous-methods
我有以下代码:
public List<IWFResourceInstance> FindStepsByType(IWFResource res)
{
List<IWFResourceInstance> retval = new List<IWFResourceInstance>();
this.FoundStep += delegate(object sender, WalkerStepEventArgs e)
{
if (e.Step.ResourceType == res) retval.Add(e.Step);
};
this.Start();
return retval;
}
Run Code Online (Sandbox Code Playgroud)
请注意我如何将我的事件成员(FoundStep)注册到本地就地匿名函数.
我的问题是:当函数'FindStepByType'结束时 - 匿名函数是否会从事件的委托列表中自动删除,或者我必须在逐步退出函数之前手动删除它?(我该怎么做?)
我希望我的问题很明确.
Kit*_*Kit 40
您的代码有一些问题(您和其他人已经确定了一些问题):
要修复此问题,仍然使用匿名委托,将其分配给局部变量,然后删除finally块中的处理程序(在处理程序抛出异常时必需):
public List<IWFResourceInstance> FindStepsByType(IWFResource res)
{
List<IWFResourceInstance> retval = new List<IWFResourceInstance>();
EventHandler<WalkerStepEventArgs> handler = (sender, e) =>
{
if (e.Step.ResourceType == res) retval.Add(e.Step);
};
this.FoundStep += handler;
try
{
this.Start();
}
finally
{
this.FoundStep -= handler;
}
return retval;
}
Run Code Online (Sandbox Code Playgroud)
使用C#7.0+,您可以使用本地函数替换匿名委托,从而实现相同的效果:
public List<IWFResourceInstance> FindStepsByType(IWFResource res)
{
var retval = new List<IWFResourceInstance>();
void Handler(object sender, WalkerStepEventArgs e)
{
if (e.Step.ResourceType == res) retval.Add(e.Step);
}
FoundStep += Handler;
try
{
this.Start();
}
finally
{
FoundStep -= Handler;
}
return retval;
}
Run Code Online (Sandbox Code Playgroud)
下面是关于如何在匿名方法中取消订阅事件的方法:
DispatcherTimer _timer = new DispatcherTimer();
_timer.Interval = TimeSpan.FromMilliseconds(1000);
EventHandler handler = null;
int i = 0;
_timer.Tick += handler = new EventHandler(delegate(object s, EventArgs ev)
{
i++;
if(i==10)
_timer.Tick -= handler;
});
_timer.Start();
Run Code Online (Sandbox Code Playgroud)
不,它不会被自动删除.从这个意义上讲,匿名方法和"普通"方法之间没有区别.如果需要,您应手动取消订阅活动.
实际上,它会捕获其他变量(例如res在您的示例中)并使它们保持活动状态(防止垃圾收集器收集它们).