[英]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.