簡體   English   中英

似乎無法通過引用傳遞EventArgs

[英]Can't seem to Pass EventArgs By Reference

我有一堂課引發一個事件。 我希望訂戶能夠修改在EventArgs中傳遞的值。

在引發事件的班級中:

    class Factory
    {
    public event EventHandler<MessageReceivedEventArgs> MessageReceived;

    private IServerLib _myObject;

    public void Connect()
    {
        _myObject = new ServerLib();
        _myObject.AddMessageReceivedHandler((short terminal, ref string message, ref short functionNo) =>
        {
            MessageReceivedEventArgs args = new MessageReceivedEventArgs { Terminal = terminal, Message = message, FunctionNo = functionNo };
            MessageReceivedEvent(ref args);
        });
    }

    private void MessageReceivedEvent(ref MessageReceivedEventArgs args)
    {
        EventHandler<MessageReceivedEventArgs> handler = MessageReceived;
        if (handler != null)
        {
            handler(this, args);
        }
    }

    public class MessageReceivedEventArgs : EventArgs
    {
        public short Terminal { get; set; }
        public string Message { get; set; }
        public short FunctionNo { get; set; }
    }
}


interface IServerLib
    {
        void AddMessageReceivedHandler(MessageReceivedEventHandler action);
    }
    public delegate void MessageReceivedEventHandler(short terminal, ref string message, ref short functionNo);

訂戶(恰好是VB)如下所示:

Dim WithEvents _va As MyAssembly.MyClass

Private Sub _va_MessageReceived(sender As Object, e As Factory.MessageReceivedEventArgs) Handles _va.MessageReceived
    Debug.WriteLine($"Message: {e.Message} Terminal: {e.Terminal} Function: {e.FunctionNo}")
    If e.Message = "1" Then
        e.Message = ""
        e.FunctionNo = 0
        Debug.WriteLine("Cancelled")
    End If
End Sub

這引發了事件,但是設置e.Message和e.Function似乎沒有設置值。 難道我做錯了什么?

問題在於使用此行:

var args = new MessageReceivedEventArgs
           { Terminal = terminal, Message = message, FunctionNo = functionNo };

它將所有變量復制到事件args類。 在此處進行更改不會自動在另一端(在其中添加ref )進行更改。 這不是一個很好的解決方案,但是為了向您證明這是問題所在,請在handler(this, args)之后添加此代碼:

message = args.Message;
functionNo = args.FunctionNo;

這將導致ref覆蓋值。

似乎您認為您的“ ref”參數應該受到上述代碼的影響,但事實並非如此。 是的,您通過引用MessageReceivedEvent函數傳遞message ,但是隨后將其分配給MessageReceivedEventArgs.Message ,這是通過值而不是通過引用發生的。

結果,當您在VB代碼中修改MessageReceivedEventArgs.Message時- message變量不會受到影響(但MessageReceivedEventArgs.Message當然受到影響),盡管您通過引用將其傳遞了。

相反,您應該做的是將MessageReceivedEventArgs實例直接傳遞給您的函數(而不是在該函數內部創建):

private void MessageReceivedEvent(MessageReceivedEventArgs args)
{
    EventHandler<MessageReceivedEventArgs> handler = MessageReceived;
    if (handler != null)
    {
        handler(this, args);
    }
}

首先,不需要ref即可更改MessageReceivedEventArgs的屬性。 對象變量只是指向內存中真實對象的指針,因此您已經在更改其屬性。 如果您需要訂戶更改引用本身(即,將指針重置為另一個對象),則需要使用ref 其次,這種設計很糟糕,因此我不確定我是否理解問題。 無論如何,我將提供一種引發事件並在此之后使用更改后的值的正確方法。

class Factory 
{
    public event EventHandler<MessagereceivedEventArgs> MessageReceived;

    void ReceiveMessage(string Message)
    {
        // Do something with the Message

        // Then let your subscribers know that the message has been processed:
        if (MessageReceived != null)
        {
            var ea = new MessageReceivedEventArgs();
            ea.Message = Message;
            // Set ea properties as appropriate 
            MessageReceived(this, ea);
            // Check ea properties for change
            if (ea.Message != Message)
            {
                // A subscriber has changed the message in the MessageReceivedEventArgs
            }
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM