c# - 取消订阅委托与函数中的事件
问题描述
为什么当事件处理程序定义为函数时 C# 允许取消订阅事件,但当事件处理程序定义为委托时不允许?
考虑以下有效的代码:
void SomeFunction()
{
var eventRaiser = ClassRaisingEvent.GetEventRaiser();
void handler(object sender, EventArgs ev)
{
ProcessData(ev);
eventRaiser.OnEvent -= handler;
}
eventRaiser.OnEvent += handler
eventRaiser.Process();
}
但这无法在指定的位置编译:
void SomeFunction()
{
var eventRaiser = ClassRaisingEvent.GetEventRaiser();
DelegateType handler = (object sender, EventArgs ev) =>
{
ProcessData(ev);
eventRaiser.OnEvent -= handler; // FAILS here with "Use of unassigned local variable 'handler '"
}
eventRaiser.OnEvent += handler
eventRaiser.Process();
}
编辑:这个问题不是如何退订。这就是为什么(在技术意义上)函数名称被捕获在函数的范围内,但委托的不是。
EDIT2:在此处回答 (尤其是答案中的第 2 点)解释了我所看到的行为。
解决方案
本地函数是在编译时定义的,就像其他函数一样。handler
但是,该变量仅在运行时才知道。因此,正如编译器告诉您的那样,您不能在handler
变量被赋值之前使用该变量,这意味着在}
您的委托关闭之后。
要使第二个代码段正常工作,您可以做的是首先初始化变量:
void SomeFunction()
{
var eventRaiser = ClassRaisingEvent.GetEventRaiser();
DelegateType handler = null;
handler = (object sender, EventArgs ev) =>
{
ProcessData(ev);
eventRaiser.OnEvent -= handler;
};
eventRaiser.OnEvent += handler;
eventRaiser.Process();
}
推荐阅读
- javascript - 如何在循环结束时返回数组(新手问题)
- spring-boot - 在 Axon Aggregate 中重放的原因
- r - 为什么 as.Date 为有效日期返回 NA?
- azure - 构建/发布管道的执行是否会创建一个新的基础文件夹,其路径包含代理编号或构建/发布编号?
- javascript - fastify.setValidatorCompiler 不是一个函数
- javascript - 如何将事件传递给 JavaScript 类中的方法?
- typescript - 导入的函数给出 TypeError: ... is not a function
- node.js - 我的 Node.js 应用程序无法作为 Kubernetes 部署的一部分启动
- r - 如何在 R 中运行面板数据
- spring - 能够使用 entitymanager.persist() 持久化数据,但无法在 spring hibernate 应用程序中使用 entitymanager.find()