我正在做一个使用异步TCP套接字的小型多线程应用程序,但我会明白:我正在使用自定义事件从表单中读取值,并且事件使用的委托在完成时返回一个字符串.
我的问题是:这是正确的吗?可以从事件中返回值吗?或者有更好的方法吗?(比如使用表单的简单委托来读取值)
从事件中返回值通常很尴尬.实际上,我发现在一组传递给事件的自定义EventArgs中包含一个可写属性要容易得多,然后在事件触发后检查 - 类似于WinForms FormClosing事件的Cancel属性.
我不认为这是一个好主意......事件基本上是多播代理,因此可以有多个处理程序.在这种情况下你会得到哪个回报值?
我能想到的最接近的例子是WinForms中的FormClosing事件.它允许表单通过将eventArgs.Cancel属性设置为true来取消事件.为了让你做类似的事情,你可以定义你自己的事件args类,返回值作为该类的属性.然后每当你举起事件时传递一个事件args对象.提出事件的人可以检查事件args对象的返回值.接收事件的其他人也可以检查或更改事件args对象.
更新:我刚刚遇到AppDomain.AssemblyResolve事件,它似乎是一个返回值的事件.您似乎只需要声明一个返回值的委托类型,然后使用该委托类型定义您的事件.不过,我还没有尝试创建自己的事件.在事件参数上使用属性的一个优点是事件的所有订阅者都可以看到先前订阅者返回的内容.
我知道这是在帖子后的年龄,但想到添加评论与代码解释达斯汀坎贝尔答案,如果有人遇到这个线程.我在试图决定什么是最佳实践时遇到了这个帖子,这就是答案的意思.
创建自己的自定义事件处理程序类
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 ; } }
因此,当您创建事件委托时,您可以使用您创建的事件args.
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 } }
注意:只有最后一个事件才会返回结果.
class Program { static event FuncTheEvent; static void Main(string[] args) { TheEvent += new Func (Program_TheEvent); TheEvent +=new Func (Program_TheEvent2); TheEvent += new Func (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; } }
我不知道这是不是最好的做法,但我是这样做的.
FuncIsDataValid; // some other code .... isValid = true; if (IsDataValid != null) { foreach (Func func in IsDataValid.GetInvocationList()) { isValid &= func(Row); } }