在声明的行上创建委托函数,可能的问题
本文关键字:函数 问题 声明 创建 | 更新日期: 2023-09-27 18:09:53
如果我有这样的内容:
void SomeFunction(onCallBackDelegate)
{
SomeClass.OnEvent += () => { onCallBackDelegate }
}
每次调用SomeFunctioni时,函数被加载到另一个函数的顶部会有问题吗?是否有一种方法来减轻它(即,当声明的函数被调用,它是从someecclass . onevent删除)?
除了不知道是否附加了处理程序之外,匿名处理程序的问题是您无法在事后将它们从事件中分离出来。对于您的特定示例,如果onCallBackDelegate
具有与事件委托相同的签名,则没有必要将其包装在匿名方法中,只需直接附加委托即可。
关于多次订阅,根据方法的实际作用,您可以选择注册一次(请记住,这对于多线程访问是不安全的):
// client is making sure that the handler doesn't get
// attached twice
bool _callbackRegistered;
void SomeFunction(Action onCallBackDelegate)
{
if (_callbackRegistered)
return;
_callbackRegistered = true;
SomeClass.OnEvent += onCallBackDelegate;
}
或者,你可以检查事件的调用列表是否已经包含委托,但你只能在事件的父类中这样做,即
class SomeClass
{
private event Action SomeEvent;
// the event is private, and we can only subscribe
// through this method
public void Subscribe(Action callback)
{
// 'callback' already attached?
if (SomeEvent != null && SomeEvent.GetInvocationList().Contains(action))
return;
SomeEvent += callback;
}
public void Unsubscribe(Action callback)
{
SomeEvent -= callback;
}
}
还有一种方法是在附加处理程序之前分离处理程序,因为如果之前没有附加处理程序,则分离处理程序不会抛出异常:
public void Subscribe(Action callback)
{
// detach if already attached
SomeEvent -= callback;
// attach
SomeEvent += callback;
}
第二种模式可能会提供一种错误的安全感,因为如果您继续附加匿名处理程序,Contains
方法将无法检测到重复的委托。换句话说:
void Handler() { }
// this will subscribe the handler only once:
someClass.Subscribe(Handler);
someClass.Subscribe(Handler);
// this will unsubscribe the handler and leave the invocation list empty
someClass.Unsubscribe(Handler);
// but this will subscribe **both** anonymous handlers:
someClass.Subscribe(() => Handler());
someClass.Subscribe(() => Handler());
// and this won't do anything
someClass.Unsubscribe(() => Handler());
然而,根据我的经验,这两种模式很可能都是不必要的。在大多数情况下,您将实例化一个类(它提供某种功能)并在那里附加到它的处理程序,只有一次:
// attach here and forget it
var someClass = new SomeClass();
someClass.OnEvent += Handler;
// once the someClass instance is no longer used, it will get
// collected and there is no need to detach your handler
每次调用SomeFunction(onCallBackDelegate)
时,onCallBackDelete将被添加到事件订阅者列表中。这本身不是问题,当事件触发时调用每个注册的onCallBackDelegate
。这取决于onCallBackDelegate
做什么,这是否会给你的代码带来问题。在StackOverflow上有许多答案,展示了防止多次添加相同处理程序的方法。例如