在声明的行上创建委托函数,可能的问题

本文关键字:函数 问题 声明 创建 | 更新日期: 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上有许多答案,展示了防止多次添加相同处理程序的方法。例如