代码之家  ›  专栏  ›  技术社区  ›  Hugo

从事件返回值-是否有良好的实践?

  •  36
  • Hugo  · 技术社区  · 15 年前

    我正在做一个使用异步TCP套接字的小的多线程应用程序,但我要说的是:我正在使用一个自定义事件从窗体中读取一个值,该事件使用的委托在完成时返回一个字符串。

    我的问题是:这是正确的吗?是否可以从事件返回值?或者有更好的方法吗?(就像使用表单的简单委托读取值一样)

    9 回复  |  直到 8 年前
        1
  •  37
  •   Dustin Campbell    15 年前

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

        2
  •  28
  •   Thomas Levesque    15 年前

    我觉得这不是个好主意…事件基本上是多播委托,因此可以有多个处理程序。在这种情况下,您将接受哪个返回值?

        3
  •  16
  •   Don Kirkby    14 年前

    我能想到的最接近的例子是WinForms中的FormClosing事件。它允许窗体通过将EventArgs.Cancel属性设置为true来取消事件。为了执行类似的操作,您将使用返回值定义自己的事件args类作为该类的属性。然后在每次引发事件时传递事件args对象。引发事件的任何人都可以检查事件args对象的返回值。其他接收事件的人也可以检查或更改事件args对象。

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

        4
  •  13
  •   Diego Jancic    10 年前

    我知道这已经是发帖后的一段时间了,但是我想用代码添加注释来解释达斯汀·坎贝尔的回答,如果有人遇到这个问题的话。我在决定什么是最佳实践时遇到了这篇文章,这就是答案的含义。

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

    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
        }
    }
    
        5
  •  9
  •   Alatey    10 年前

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

    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;
        }        
    }
    
        6
  •  8
  •   Kirk Woll    11 年前

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

       Func<DataRow, bool> IsDataValid;
    
       // some other code ....
    
       isValid = true;
       if (IsDataValid != null)
       {
          foreach (Func<DataRow, bool> func in IsDataValid.GetInvocationList())
          {
             isValid &= func(Row);
          } 
       }
    
        7
  •  1
  •   sammybar    10 年前

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

        8
  •  0
  •   user1218233    8 年前

    我像这样循环EventArgs的属性,并提取出它的x和y值。

    private void navbarcontrol1_click(对象发送器,事件参数e) { int x=0; INTY=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
  •  -1
  •   dude    13 年前
    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)
        }
    }