c#使用对事件成员的引用

时间:2012-01-12 23:25:20

标签: c# events

有人知道为什么这不可能吗? 如果事件只是MulticastDelegate实例,您应该能够在代码中引用它。编译器说EventA只能在 - =或+ =。

的左侧
public delegate void MyDelegate();
public event MyDelegate EventA;

public void addHandlerToEvent(MulticastDelegate md,Delegate d){
 md+=d;

}

///
addHandlerToEvent(EventA,new MyDelegate(delegate(){}));

3 个答案:

答案 0 :(得分:1)

事件由多播委托支持,是的,但它们的目的是提供observer pattern的实现,其中观察者(在这种情况下为委托)可能只能注册(+=)或未注册( -=)。如果在类本身之外可以正常访问支持委托,则客户端代码可能会干扰在其他地方注册的无关委托,这可能会搞砸。它也有点与观察者模式的关系,看看哪些其他事物正在观察有问题的事件。

如果你需要对支持委托进行这种操作,那么它必须在类中完成(它被视为常规委托而不是事件)。

您还可以显式实现支持委托,并提供一个访问者来注册/取消注册:

private EventHandler SomeEvent;

public event EventHandler
{
    add
    {
        SomeEvent += value;
    }
    remove
    {
        SomeEvent -= value;
    }
}

这样,您可以根据需要提供对代理的直接访问。为了订阅/取消订阅作为事件(而不是原始委托),最好提供公共访问权限,否则您可能会遇到委托人数据竞争的线程安全问题。

答案 1 :(得分:1)

事件不是多播委托,就像属性不是字段一样。

C#的event语法通过提供用于添加和删除处理程序委托的语法糖来包装多播委托以使生活更轻松。您的事件定义将编译为以下内容:

private MyDelegate _EventA;

public event MyDelegate EventA
{
    [MethodImpl(MethodImplOptions.Synchronized)]
    add 
    { 
        _EventA = (MyDelegate)Delegate.Combine(_EventA, value);
    }

    [MethodImpl(MethodImplOptions.Synchronized)]
    remove 
    { 
        _EventA = (MyDelegate)Delegate.Remove(_EventA, value);
    }
}

当您在活动中使用addremove时,系统会调用展开的事件定义中的operator +=operator -=方法。

这样做是为了隐藏多播委托的内部,但是公开了一种实现发布/订阅事件的简单方法。能够获得底层委托(在其定义的类之外)将破坏有意的封装。

答案 2 :(得分:1)

事件是绑定一对添加/删除方法(*)的成员,每个方法都接受与事件签名对应的委托。默认情况下,C#编译器将为每个事件自动定义一个MultiCast委托字段以及添加和删除成员,这些成员将接受传入的委托并在MulticastDelegate字段中添加或删除它们。语句myEvent += someMethod;在定义事件的类之外执行时,是myEvent.AddHandler(someMethod)所必需的语法简写,myEvent -= someMethod;myEvent.RemoveHandler(someMethod)除外,没有办法在C#中调用添加/删除方法,但使用+=-=表示法除外。

在定义事件的类中使用+=-=表示法时,事情有点棘手,因为自动生成的事件代码定义的字段与事件的名称相同, myEvent += someMethod;的行为因C#的不同版本而异。

(*)技术上是一个三重奏,因为一个事件还包括一个'加注'方法,但实际上该方法基本上从未使用过。