时间:2010-07-24 14:05:12

标签: c# .net events event-handling

11 个答案:

答案 0 :(得分:33)

答案 1 :(得分:16)

答案 2 :(得分:9)

答案 3 :(得分:5)

答案 4 :(得分:5)

答案 5 :(得分:5)

在c#中,事件可以是两种类型

<强> 1。组播
2. UnitCast

多播事件是指具有多个订户的事件。当引发多播事件时,将调用多个处理程序,因为您订阅了多个事件处理程序。 那么,多播事件是用来调用多个处理程序而多播处理程序不能有返回类型的原因??

因为如果多播委托有返回类型,那么每个事件处理程序都会返回一些值,一个事件处理程序的返回值将被下一个事件处理程序值替换。

假设您有一个多播委托,如下所示

public delegate int buttonClick;

public event buttonClick onClick;

onClick += method1
onclick += method2
onclick += metho3

当引发此事件时,method1返回的值将被method2返回的值替换,最终将只接收method3的值。

因此,在Multicast委托的情况下,始终建议不要返回任何值。

但是在单播删除的情况下,您只有一个订阅者。因此,您可以返回实现目标的价值

因此,对于多播委托 - 没有返回类型 对于单播委托 - 可以有返回类型

多播委托也可以返回多个值,但必须手动引发该事件。

如果您选择多播委托也应返回值,请假设我有一个绑定到4事件处理程序的事件,它需要两个整数,一个处理程序添加,第二个减法和第三个乘法和最后一个除法。因此,如果您想获得所有处理程序的返回类型,则必须以下列方式手动引发事件,

var handler = _eventToRaised.GetInvocationList();
foreach(var handler in handlers)
{
  if(handler != null)
   {
    var returnValue = handler()// pass the values which delegate expects.
   }

}

答案 6 :(得分:3)

答案 7 :(得分:3)

答案 8 :(得分:1)

答案 9 :(得分:0)

答案 10 :(得分:0)

介绍性注释: 如果您要调用的[single]方法与调用代码处于相同或更低的依赖级别,则可以继续进行调用,而无需发生事件。所以;仅当至少有一个事件引发(调用)要从上一层调用方法时,事件才有用。

现在,长答案取决于您是编写自己的委托并将其标记为事件(1)还是使用EventHandler(2):

  1. 如果编写自己的委托,则可以只返回所需的结果。但是问题是,对于多播委托,仅返回最终订阅方法的结果。


    public class TestEvents
    {
        public event SomethingHappenedHandler1 SomethingHappened1;
        public event EventHandler SomethingHappened2;
    
        public void Run()
        {
            SomethingHappened1 += Scenario_DelegateOnly.SubscriberMethod;
            SomethingHappened1(this, 13, 15);
    
            SomethingHappened2 += Scenario_EventHandlerAndEventArgs.SubscriberMethod;
            SomethingHappened2(this, new MyEventArgs2(33, 35));
        }
    }
    
    //1
    public delegate int SomethingHappenedHandler1(object sender, int arg1, int arg2);
    public static class Scenario_DelegateCanHaveReturnValue
    {
        public static int SubscriberMethod(object sender, int arg1, int arg2)
        {
            Console.WriteLine($"{sender.ToString()} {arg1} {arg2} ... returning {arg1} * {arg2}");
            return arg1 * arg2;
        }
    }
    
    //2
    public static class Scenario_EventHandlerAndEventArgs
    {
        public static void SubscriberMethod(object sender, MyEventArgs2 args)
        {
            Console.WriteLine($"{sender.ToString()} {args.arg1} {args.arg2}");
        }
    }
    public class MyEventArgs2 : EventArgs
    {
        public MyEventArgs2(int arg1, int arg2)
        {
            this.arg1 = arg1;
            this.arg2 = arg2;
        }
        public int arg1;
        public int arg2;
    }

  1. 如果使用方法的EventHandler签名,则返回类型将始终为“ void”。大多数情况下,引发事件是忘记操作(例如button_Click),我们可能并不关心操作结果,但是当我们确实需要一些反馈时,总有一种解决方法,因为订阅者方法可以将这些结果保存到发布者的属性中;它只需要转换“发送者”对象即可获得发布者的实例[除非订阅者在依赖者之下低于发布者,否则这应该没问题(场景指出,我们不需要事件开始!)。