测试代码如下:
(1)
public delegate int Del(int i);
public ref struct C {
   int i;
   event Del^ MyEvent;
   //Del^ MyEvent;   void FireEvent() {
      i = MyEvent(i);
   }
};ref struct EventReceiver {
   int OnMyClick(int i) { return ++i; }
};
void funcfor_event()
{
    C c;
    c.i = 687;    c.FireEvent();
    Console::WriteLine(c.i);
    c.i = 688;
    Console::WriteLine(c.i);    EventReceiver^ MyEventReceiver1 = gcnew EventReceiver();
EventReceiver^ MyEventReceiver2 = gcnew EventReceiver();
EventReceiver^ MyEventReceiver3 = gcnew EventReceiver();
    c.MyEvent += gcnew Del(MyEventReceiver1, &EventReceiver::OnMyClick);
c.MyEvent += gcnew Del(MyEventReceiver2, &EventReceiver::OnMyClick);
c.MyEvent += gcnew Del(MyEventReceiver3, &EventReceiver::OnMyClick);
    c.FireEvent();
    //c.FireEvent();
    Console::WriteLine(c.i);
}
我的理解是如果c.MyEvent在委托列表中添加了三个事件,那么这三个事件都应该执行,如果是按照顺序执行则i最后的值应该增加3,但是现在i的值确是689,请问是为什么?(2)
public delegate int Del(int i);
public ref struct C {
   int i;
   event Del^ MyEvent;
   //Del^ MyEvent;   void FireEvent() {
      i = MyEvent(i);
   }
};ref struct EventReceiver {
   int OnMyClick(int i) { return ++i; }
};int f(int i)
{
    cout<<"ssssssss"<<i<<endl;
    return 1;
}int f1(int i)
{
    cout<<"zzzzzzzzz"<<i<<endl;
    return 1;
}
void funcfor_event()
{
    C c;
    c.i = 687;    c.FireEvent();
    Console::WriteLine(c.i);
    c.i = 688;
    Console::WriteLine(c.i);    EventReceiver^ MyEventReceiver = gcnew EventReceiver();
    c.MyEvent += gcnew Del(MyEventReceiver, &EventReceiver::OnMyClick);
    c.MyEvent += gcnew Del(f);
    c.MyEvent += gcnew Del(MyEventReceiver, &EventReceiver::OnMyClick);
    c.MyEvent += gcnew Del(f1);;
    c.FireEvent();
    //c.FireEvent();
    Console::WriteLine(c.i);
}
如(2)这部分代码,在c.MyEvent委托列表中增加了f和f1两个事件,执行的结果是:
0
688
ssssssss688
zzzzzzzzz688
1
请按任意键继续. . .
不明白为什么顺序上有区别,而且zzzzzzzzz688为什么对i没有加1?

解决方案 »

  1.   

    1.写这么乱的代码纯粹是折磨自己;
    2.问题1三个事件的输入参数都是688,所以输出都是689,你可以在事件响应函数里跟踪下是否正确。没有累加性,int是值对象的,你可以改用ref看看。
    3.问题三你return的是1,不知道如何能加1?delegate维护一个链表,所有是有顺序的。
      

  2.   

    可能没有表达清楚意思:
    事件的+=运算符在(1)例子中操作了3次,那么delegate列表中应该有3个需要运行的函数
    类似于一个指针 P 指向字符串(函数)的入口,那么3个函数在执行的时候应该是按照顺序执行的(不管什么顺序),第一个执行完了返回然后执行第二个,所以我理解的应该对i累加,但事实不是这样,所以不知道为什么对第二个问题:
    如果代码改为这样:
        EventReceiver^ MyEventReceiver = gcnew EventReceiver();
        c.MyEvent += gcnew Del(f);
        c.MyEvent += gcnew Del(MyEventReceiver, &EventReceiver::OnMyClick);
        //c.MyEvent += gcnew Del(f1);                   --把这一行给注释掉
        c.FireEvent();
    运行结果是:
    0
    688
    ssssssss688
    689
    请按任意键继续. . .
    这里f()的返回值没有起作用,对EventReceiver::OnMyClick执行后c.i自加了1;不注释c.MyEvent += gcnew Del(f1); 这句
    运行结果是:
    0
    688
    ssssssss688
    zzzzzzzzz688
    1
    请按任意键继续. . .
    就是这个地方很不能理解,跟踪不出结果
    结果分析应该是首先执行了f()函数,然后执行了f1()函数,而执行f()函数的时候i的返回值没有起作用,但是在执行f1()后,返回值1确改变了c.i的值,同时,EventReceiver::OnMyClick这个函数没有起作用,所以前后的结果不能理解。
      

  3.   

    你这里几个问题其实是一个问题,理解了都通,不理解都想不通。
    这里添加的多个事件的确都执行了,而且肯定是按照添加的顺序执行的,但是你用成员变量i接收返回值仅一次,接收的是最后一次执行的返回值,如果添加了4个事件,且每个事件的返回值都不同,你会发现,i得到的将是最后一次执行的那个事件的返回值,前面几个事件的返回值被丢弃了。因此事件中不要用返回值来处理最终结果,那样是不准确的,一般是通过参数传递一个自定义的EvengArgs对象,修改其自定义属性来实现累加值的变化效果。
      

  4.   

    感谢qldsrx、hard9999
    测试了一下,确实存在这样的问题,执行顺序是按照添加顺序,而且i的返回值确实只有最后一个函数起作用。
    如果不知道事件的实现方式确实很难理解。
    这种方式对事件传递参数要求就很高了~!
      

  5.   

    在问一下,对add运行方式和传递参数的问题,在哪里可以找到相关的资料?
    msdn2008里面没有找到
      

  6.   

    你可以参考控件的各种事件,比如KeyDown事件中,可以捕获到按下的是哪个按键,它的参数就是一种特殊的参数。其实换做自定义类传递进去,一样的效果。