事件监听器是否仅限于只有一个用户?

Inv*_*ion 12 c# events exception

是否可以阻止多个订阅者订阅活动?

我已经创建了一个快速示例代码片段给我的问题一些上下文但不幸的是我现在无法测试它,因为我不在我的VS机器上.

目标是:

  • 如果没有订阅者,则返回空列表.
  • 返回单个订户的返回值.
  • 如果多个订户尝试订阅该事件,则抛出异常(这是问题的关键).

这可能吗?

public delegate List<IBaseWindow> GetWindowListDelegate();
public static event GetWindowListDelegate GetWindowListEvent;

public List<IBaseWindow> GetWindowList() {

    if (GetWindowListEvent == null) {
        return new List<IBaseWindow>();
    }

    return GetWindowListEvent();
 }
Run Code Online (Sandbox Code Playgroud)

注意:我使用的是.NET 3.5 sp1.

And*_*are 15

听起来您不需要事件 - 只需公开委托本身并允许调用者自己设置委托引用.

  • AFAIK中的所有代理都是默认的多播代理,即它们可以有多个"订阅者". (9认同)
  • 没有什么难以理解的,只需删除`event`关键字,并使用=而不是+ =来"订阅" (2认同)
  • 这已经太晚了,不确定自从发布答案以来事情是否发生了变化,但是将事件更改为委托将使其容易受到其他类调用它的影响。如何实现单一订阅机制而不让其他类触发事件? (2认同)

Joh*_*lla 9

您可以使用事件访问器来完成此任务.类似于以下内容:

  private EventHandler _h;
  public event EventHandler H {
      add {
         if (...) { // Your conditions here.
                    // Warning (as per comments): clients may not
                    // expect problems to occur when adding listeners!
           _h += value;
         }
      }
      remove {
         _h -= value;
      }
  }
Run Code Online (Sandbox Code Playgroud)

正如安德鲁指出的那样,你并不需要事件来完成这一任务.你需要它们有什么特别的原因吗?

  • +1作为答案.我想补充要小心使用这种技术 - 当.NET开发人员看到了类型声明的情况下,*安全*假设(因此安全甚至有不是一个理由,否则检查)是一种新的听众可以毫无问题地增加. (8认同)

Tho*_*que 7

只是为了完成John的答案,这里是一个只允许一个处理程序的事件的工作实现:

class Foo
{
    private EventHandler _bar;
    public event EventHandler Bar
    {
        add
        {
            if (_bar != null || value.GetInvocationList().Length > 1)
            {
                throw new InvalidOperationException("Only one handler allowed");
            }
            _bar = (EventHandler)Delegate.Combine(_bar, value);
        }
        remove
        {
            _bar = (EventHandler)Delegate.Remove(_bar, value);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,公开委托而不是事件不会阻止多个处理程序:由于.NET委托是多播的,因此一个委托可以表示对多个方法的调用.但是,您可以将委托作为属性公开,并在setter中执行与上面代码中相同的检查.

无论如何,正如其他人所指出的那样,防止一个事件的多个处理程序可能不是一个好主意......对于使用它的开发人员来说会非常困惑.