从事件中返回一个值——这有啥好的做法吗?

Posted

技术标签:

【中文标题】从事件中返回一个值——这有啥好的做法吗?【英文标题】:Return a value from an Event -- is there a Good Practice for this?从事件中返回一个值——这有什么好的做法吗? 【发布时间】:2010-11-15 15:39:00 【问题描述】:

我正在做一个使用异步 TCP 套接字的小型多线程应用程序,但我要直截了当:我正在使用自定义事件从表单中读取值,并且事件使用的委托返回一个完成后的字符串。

我的问题是:这是正确的吗?从事件中返回值可以吗?还是有更好的方法来做到这一点? (比如使用简单的表单委托来读取值)

【问题讨论】:

【参考方案1】:

从事件返回值通常很尴尬。在实践中,我发现在传递给事件的一组自定义 EventArgs 中包含可写属性要容易得多,然后在事件触发后进行检查——类似于 WinForms FormClosing 事件的 Cancel 属性。

【讨论】:

能否详细说明include a writable property on a set of custom EventArgs that is passed to the event 部分? @Odys 自定义 EventArgument 对象。创建结果所在的属性。【参考方案2】:

我认为这不是一个好主意...事件基本上是多播委托,因此可以有多个处理程序。在这种情况下,您将采用哪个返回值?

【讨论】:

【参考方案3】:

我知道这是帖子发布后的年龄,但我想用代码添加评论来解释达斯汀坎贝尔的答案,如果其他人遇到这个帖子。我在尝试确定最佳实践时遇到了这篇文章,这就是答案的含义。

创建您自己的自定义事件处理程序类

public class myCustomeEventArgs:EventArgs

    public bool DoOverride  get; set; 
    public string Variable1  get; private set; 
    public string Variable2 get; private set; 

    public myCustomeEventArgs(string variable1 , string variable2 )
    
        DoOverride = false;
        Variable1 = variable1 ;
        Variables = variable2 ;
    

因此,当您创建事件委托时,您可以像这样使用您创建的事件参数。

public delegate void myCustomeEventHandler(object sender, myCustomeEventArgs e);

并在引发事件的类中声明该事件。

public event myCustomeEventHandler myCustomeEvent;

因此,当您在类中触发事件时,侦听事件的类可以在事件主体中设置 e.DoOverride = true;因为它将在触发事件的类中声明。

例如火灾事件:

if(myCustomeEvent != null)

    var eventArgs = new myCustomeEventArgs("Some Variable", "Another Varaible");
    myCustomeEvent(this, eventArgs);
    //Here you can now with the return of the event work with the event args
    if(eventArgs.DoOverride)
    
       //Do Something
    

【讨论】:

你怎么知道活动什么时候“回归”? 事件在引发它们的同一线程上运行。运行myCustomeEvent(...) 的代码会将控制权(在同一线程上运行)传递给所有订阅的事件处理程序。一旦他们的所有代码都运行完毕,控制权将在调用myCusomeEvent(...) 后立即返回到指令。如果没有订阅者,或者有订阅者将事件重新广播到另一个线程,则eventArgs 上的所有属性都将具有其默认值(bool 为 false,字符串为 null)。 【参考方案4】:

我能想到的最接近的例子是 WinForms 中的 FormClosing 事件。它允许表单通过将 eventArgs.Cancel 属性设置为 true 来取消事件。为了让您做类似的事情,您可以定义自己的事件 args 类,并将返回值作为该类的属性。然后在引发事件时传递一个事件 args 对象。引发事件的人可以检查事件 args 对象的返回值。接收事件的其他人也可以检查或更改事件 args 对象。

更新:我刚刚遇到了AppDomain.AssemblyResolve 事件,它似乎是一个返回值的事件。似乎您只需要声明一个返回值的委托类型,然后使用该委托类型定义您的事件。不过,我还没有尝试过创建自己的活动。在 event 参数上使用属性的一个好处是,该事件的所有订阅者都可以看到以前的订阅者返回了什么。

【讨论】:

注意:您可以使用任何委托来定义事件,因此也可以定义像public event Func<string, string, bool> SomeEvent; 这样可以调用为bool r = SomeEvent("foo", "bar"); 的事件【参考方案5】:

注意:只有最后一个事件返回结果。

class Program

static event Func<string, bool> TheEvent;

    static void Main(string[] args)
    
        TheEvent += new Func<string, bool>(Program_TheEvent);
        TheEvent +=new Func<string,bool>(Program_TheEvent2);
        TheEvent += new Func<string, bool>(Program_TheEvent3);
        var r = TheEvent("s"); //r == flase (Program_TheEvent3)
    

    static bool Program_TheEvent(string arg)
    
        return true;
    

    static bool Program_TheEvent2(string arg)
    
        return true;
    

    static bool Program_TheEvent3(string arg)
    
        return false;
            

【讨论】:

谢谢。跨 WCF 服务为我工作【参考方案6】:

我不知道这是否是最佳做法,但我是这样做的。

   Func<DataRow, bool> IsDataValid;

   // some other code ....

   isValid = true;
   if (IsDataValid != null)
   
      foreach (Func<DataRow, bool> func in IsDataValid.GetInvocationList())
      
         isValid &= func(Row);
       
   

【讨论】:

【参考方案7】:

如果事件返​​回一个值并且注册了多个处理程序,则事件返回最后调用的处理程序的结果值。 在http://blogs.msdn.com/b/deviations/archive/2008/11/27/event-handlers-returning-values.aspx 中查找示例

【讨论】:

答案中的链接已失效 - “找不到页面”【参考方案8】:

我像这样循环了 EventArgs 的属性并提取了它的 X 和 Y 值。

private void navBarControl1_Click(object sender, EventArgs e)

    int _x = 0;
    int _y = 0;
    
    Type t = e.GetType();
    IList<PropertyInfo> props = new List<PropertyInfo>(t.GetProperties());

    foreach (PropertyInfo prop in props)
    
        if (prop.Name == "X")
        
            object propValue = prop.GetValue(e, null);
            _x = Convert.ToInt32(propValue);
        
        if (prop.Name == "Y")
        
            object propValue = prop.GetValue(e, null);
            _y = Convert.ToInt32(propValue);
        
    

【讨论】:

【参考方案9】:
void method()

    list<string> strings = new list<string>();

    dostuff += stuff;
    dostuff += stuff;

    dostuff(this, new EventHandlerArgs() Parameter = strings )

    foreach(string currString in strings)
    
          //....
    


void stuff(object sender, EventHandlerArgs e)

    list<string> strings = e.Parameter as list<string>;

    if (strings != null)
    
        strings.Add(MyString)
    

【讨论】:

欢迎来到***!最好为示例代码提供简短描述以提高发布准确性:)

以上是关于从事件中返回一个值——这有啥好的做法吗?的主要内容,如果未能解决你的问题,请参考以下文章

git:存储库会自然膨胀吗?有啥好的做法可以缓解这种情况

在 CSS 中对 RGB 颜色值使用十六进制而不是十进制有啥好的理由吗?

有啥好的关系数据库教程吗? [关闭]

JQOM 有啥好的参考吗?

学习C语言的指针部分有啥好的方法吗?真的很难啊!!

有啥好的 Pig Accumulator 接口实现的例子吗?