C# 如何在C中引用事件#

C# 如何在C中引用事件#,c#,events,reference,callback,event-handling,C#,Events,Reference,Callback,Event Handling,我有一个类,它有一个名为LengthChanged的公共事件: class Dimension { public int Length { get { return this.length; } set { if (this.length != value) { this.length = valu

我有一个类,它有一个名为
LengthChanged
的公共事件:

class Dimension
{
    public int Length
    {
        get
        {
            return this.length;
        }
        set
        {
            if (this.length != value)
            {
                this.length = value;
                this.OnLengthChanged ();
            }
    }

    protected virtual void OnLengthChanged()
    {
        var handler = this.LengthChanged;
        if (handler != null)
        {
            handler (this, System.EventArgs.Empty);
        }
    }

    public event System.EventHandler LengthChanged;

    private int length;
}
我希望能够在名为
Observer
的方法中注册/取消注册此事件的处理程序,该方法对
维度
类一无所知。我提出了两种方案,没有一种是真正令人满意的:

  • 使用
    LengthChanged
    事件定义一个接口
    ilelengthchanged
    ,然后确保
    Dimension
    实现
    ilelengthchanged
    。然后,我必须为我定义的每个接口提供一个
    Observer
    方法的实现。这绝对不够一般。我真的希望能够简单地传入对
    System.EventHandler
    事件的引用

  • 使用
    System.Action
    回调在
    Observer
    方法中注册和注销事件处理程序,如下所示:

  • class-Foo
    {
    公共无效观察员(系统行动登记册,
    系统操作(取消注册)
    {
    登记册(此为MyEventHandler);
    //跟踪注销回调,以便我们可以注销
    //稍后,如果需要,我们的事件处理程序。。。
    }
    私有void MyEventHandler(对象发送方,System.EventArgs e)
    {
    ...
    }
    }
    
    然后会像这样调用:

    Foo foo = ...;
    Dimension dim = ...;
    
    foo.Observer (x => dim.LengthChanged += x, x => dim.LengthChanged -= x);
    
    当执行时,它确实会将
    LengthChanged
    事件与内部事件处理程序
    MyEventHandler
    连接起来。但这不是很优雅。我希望能够写下以下内容:

    Foo foo = ...;
    Dimension dim = ...;
    
    foo.Observer (dim.LengthChanged);
    

    但我不知道如何才能做到这一点。也许我错过了一些很明显的东西?我想一些
    dynamic
    magic可以在某种程度上实现这一点,但这不会强制执行编译时类型检查:我不希望
    Observer
    的用户传入不满足
    System.EventHandler
    事件签名的事件引用。

    不幸的是,没有真正的方法可以做到这一点。尽管F#试图在.NET上推广这些活动,但一般来说,这些活动并不是.NET的头等公民

    传入订阅/取消订阅委托或使用指示事件名称的字符串。(后者通常较短,但在编译时显然不太安全。)


    这些是需要采取的方法-如果有更干净的方法,我相信他们会使用:(

    事件不应该被传递到另一个方法中。但是,您可以将委托传递到另一个方法中。也许,您正在寻找的只是一个简单的公共委托,而不是事件

    如果您将活动更改为此

    public System.EventHandler LengthChanged; 
    
    您可以像这样简单地将长度更改传递给观察者

    Foo foo = ...;
    Dimension dim = ...;
    foo.Observer (dim.LengthChanged); 
    

    您可以创建自定义访问器

    public event EventHandler NewEvent
    {
        add { Dimension.LengthChanged += value; }
        remove { Dimension.LengthChanged -= value; }
    }
    

    请。

    谢谢你的建议。不,我不能传递委托而不是事件;该事件可能实现
    add
    remove
    设置器,并且必须定义为一个完整的C#
    事件
    @Pierre,我明白了。在这种情况下,我要做的是声明一个委托包装器类。构造函数该类的属性接受委托。该类具有virtual AddHandler()和virtual RemoveHandler()。它还具有Invoke()方法调用委托。若要使其看起来更优雅,可以定义运算符+=、-=、+和-,调用AddHandler和RemoveHandler。用此包装类替换维度的LengthChanged事件。对于需要“添加”和“删除”的情况setters,只需重写包装类的AddHandler和RemoveHandler方法。只需我的2美分。我也做了类似的。很好的解决方案…我必须仔细考虑一下。+1对于这个不错的破解。如果像Erik Meijer这样的人不能想出更干净的解决方案,我怀疑确实没有其他方法可以做到。这很遗憾……谢谢你的支持我们的快速回复,乔恩。