刚开始用DELPHI的时候, 是不是大多数人都在ONXXXXX事件中写代码? (我也是)一直想说说这个问题. 感觉是从一开始就进入了"误区". 这种习惯感觉很不好!有些非可视的组件,尤其像TDataSet的子孙们根本就不应该在属性编辑器中有OnXXXX事件. public出来就OK了.或者TDataSet的子孙根本不应该能直接拖到TForm 或 TDataModule 上.还有像TButton.Click. 应该能像C#这样 Click += XXXX.Click会更好. 以上只是本人的一点看法. 希望大家说说一些认为值得"推敲"的东西.

解决方案 »

  1.   


    delphi 中当然可以;
    取消
    Button1.OnClick := nil;
    指向
    Button1.OnClick := MyClick;
      

  2.   

    ONXXXXX事件是Delphi封装好的事件是想给开发人员提供方便,说害人有点过了.
      

  3.   

    二楼三楼都没看明白我想说什么,  
    对于Click += XXXX.Click 我是想说C#的代理            
    button1.Click += new System.EventHandler(this.button2_Click);
    button1.Click += new System.EventHandler(this.button3_Click);to:
    除此之外,我想说,什么事都有双面性,如果什么东西都“根”开始,说不定等你所开发的东西交工之日,便是你被炒之时!
    呵. "根"打不好. 盖的永远是危楼. 
      

  4.   

    button1.Click += new System.EventHandler(this.button2_Click); 
    button1.Click += new System.EventHandler(this.button3_Click); 
    不会C#,向楼主请教一下这两句的具体作用
      

  5.   


    相当于 button2 和 button3 对 button1 说: 你结婚时要告诉我.button1被"点"的时候, 就会发出消息to button1, button2. 我要结婚了, 你们看着办吧.
      

  6.   


    那么换用Delphi的话,button1被"点"的事件就是:button2.click;
    button3.click;即单击button1时等于分别单击了button2和button3
      

  7.   

    DelphiGuy  来了就有好戏看了, 
      

  8.   

    to 11楼button2.click; 
    button3.click;
    self do something //button1自己还要做的事.感觉是button1让button2, buttn3也去做什么. 不是一种"通知". (另:我打的比方有不太恰当之处)to 12楼
    我晕! 什么意思嘛. 呵.
    to 13楼
    莫发乱想. :)
      

  9.   

    const
      AMsg = 99999;type
      TForm1 = class(TForm)
        Button1: TButton;
        Button2: TButton;
        procedure FormCreate(Sender: TObject);
        procedure Button2Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
        OldWndProc: TWndMethod;
        procedure BtnWndProc(var Message: TMessage);
      end;var
      Form1: TForm1;implementation{$R *.dfm}procedure TForm1.BtnWndProc(var Message: TMessage);
    begin
      if Message.Msg = 99999 then
        Self.Button1.Caption := FormatDateTime('hh:nn:ss', Now);
      Self.OldWndProc(Message);
    end;procedure TForm1.FormCreate(Sender: TObject);
    begin
      OldWndProc := Self.Button1.WindowProc;
      Self.Button1.WindowProc := Self.BtnWndProc;
    end;procedure TForm1.Button2Click(Sender: TObject);
    begin
      PostMessage(Button1.Handle, 99999, 0, 0);
    end;
      

  10.   


    C#中用了委托来实现的DELPHI的这种属性,也就是上面的过程函数,等C#里的委托理解为指向函数的指针应该也行吧。 从语法上是完全是C# 与  pascal 的区别不过Click += XXXX.Click 这样的实现的确比 DELPHI在publised 实现的要强一些。delphi 自动实现了button1.Click 用 Button1onClick 来实现了事件。
    要实现  C# 中的委托,可能就要改变下 procedure Button1Click(Sender:Tobject); 
    begin
      if Sender is ...   这样来实现委托的效果。  的确复杂了点。
    end;
      

  11.   

    不是很懂 C#, 但 delphi 内把 3 个 button 的 OnClick 指向同一个函数也可以实现此功能!楼主可能是想提醒初学者要灵活使用 delphi, 
    不要总按书上那样使用 delphi, 例如:
      TDataSet的子孙总是放到TForm 或 TDataModule 上,
      OnClick总是在设计时指定,
    其实需要时, 还可以用代码来实现这些功能, 而且更加灵活.初学者要领悟楼主的意思, 不要误解成 delphi 不好.虽然有段时间没用delphi做过实际开发了, (转入嵌入式开发了)
    但从经验来看, 除了驱动程序, 还没有 delphi 做不到的.
      

  12.   

    学什么总有个循序渐进的过程,不少人说delphi入手容易,不就是that吗。当然楼主的提醒也有价值。这就叫“两面性”。
      

  13.   

    delphi该从人们眼中消失的时候了
      

  14.   

    1.还有像TButton.Click. 应该能像C#这样 Click += XXXX.Click会更好. C#没学过,瞎说二句!
    这点毫无疑问,定义委托更容易解除消息事件以及订阅事件之间的藕合关系,使之更为灵活(可轻松实现合并委托之类的)。从事件设计模式上来讲,的确很不错!
    Delphi这方面实现得的确不太灵活!
    2.有些非可视的组件,尤其像TDataSet的子孙们根本就不应该在属性编辑器中有OnXXXX事件. public出来就OK了.这点相当不明白LZ的意思!
    3.TDataSet的子孙根本不应该能直接拖到TForm 或 TDataModule 上. 从快速开发角度来讲,可能会降低工作效率!
      

  15.   

    怎么说的那么复杂,简单说,c#的event就是一个事件可以顺序触发多个方法,实际上就是一个链表而已
    我曾考虑过在d2009中diy一个山寨版的泛型模板,但是rtti中关于method类型参数的信息量太少,参数传递的方式又非常复杂,如何保存和恢复stack也就变得极复杂。考虑过两三种我能想到的实现方式,要么太浪费空间要么不现实,反正是没找到一个比较理想的实现方式
      

  16.   

    俺比较菜,没有弄明白,C#的事件(委托)和Delphi的事件在本质上有什么区别。
    俺觉得C#和Delphi的事件其实本质上都是一样的,都是类的成员函数指针而已,
    只不过C#的事件是个指针链表,而Delphi只是一个指针而已。。想到这些,感觉
    C#的事件只是在使用上比Delphi稍微的简单一些,但是Delphi实现类C#的事件也应该可以的,
    譬如说:也可以先定义函数指针链表,对其赋值,尔后在 Delphi的Click事件中
    根据事先定义好的链表开始依次执行不就OK了?!如有疑问可以参考VC的MFC源码,
    那里有一段是程序启动时如何初始化 全局变量的操作,不过具体是MFC的那个源文件
    我倒是既不清楚了
    以上,个人愚见,有什么不妥之处请各位大牛见谅哈。
      

  17.   

    原来 C# 的事件使用链表实现的. 本来就慢, 这样就更加慢了!实用中, 绝大部分事件是单个的, 所以认为:
    C#为了一点点灵活性损失效率, 何况是几乎不用的灵活性, 实在得不偿失!个人认为, 这一点上, C#不如delphi, 而不是向lz说的那样
      

  18.   

    delphi的优点在于提供多层次的实现手段
    初学者、求简单快捷,可以直接使用其高层的封装:快速实现一些普通的功能;
    想实现一些特殊的功能(被初学者认为只有vc才能做到的),也可以像vc一样直接使用api进行编程,只是开发效率也与vc一样了。楼主这个问题,其实是只看到delphi的高层的封装,就以为delphi没有低级的实现手段了当然,采用控件的模式,个人现在看来,除了界面控件有必要之外,非可见的控件,其实还是采用直接的类-对象这样更简明一些
    当然,dataset也做成控件,估计是为了提供一体化的高层封装,以便能单纯靠拖放控件的方式一口气实现一个最基本的应用(demo)另外,delphi现在看来也是有一些缺憾,但是这与delphi出的早有关了
    从win32开发而言,应该是基本完美的了
      

  19.   

    关于OnXXXX,个人感觉是一种 面向方面 的雏形——呵呵
    相当于delphi提供了一个现成的应用框架,在很多地方提供 OnBeforeXXX OnAfterXXX OnXXX
    ——当然AAA被XXX的时候,执行:
      if assigned(AAA.OnBeforeXXX) then
        AAA.OnBeforeXXX(参数);
      if assigned(AAA.OnXXX) then
        AAA.OnXXX(参数);
      if assigned(AAA.OnAfterXXX) then
        AAA.OnAfterXXX(参数);
    只需要开发者根据自己的需求特点对事件的切入点再做进一步的具体实现,相当于填空
    如果某个处理,现成的框架已经足够满足了,不提供(不填)也完全能跑了
      

  20.   

    如果没OnXXXXX事件,不知多少人还没入门呢在不在事件写太多代码,只不过是习惯问题,这个问题通常被提及那个“永恒”的三层非可视的控件也有事件的,事件就是用来告诉大家,某个时刻发生了,要干活的快来,要是public出来,你指方法吗,你怎么确定这个时刻?你确定了,其他人没事件干瞪眼啊?
      

  21.   

    我以为楼主要谈MVC,进来一看发现原来只是比较静态关联事件和动态关联事件... 如果楼主喜欢的话,完全可以在Constructor里面:OnCreate := HandleCreate; OnShow := HandleShow 等等如果要说事件害人的话,害人的地方不在此..
      

  22.   

    同时期待好的MVC解决方法出现,以前只在RAPTOR那里看过个文章,感觉还是怪怪的 - -
      

  23.   

    楼主想要的是一个事件多订阅(默认情况下Delphi只支持单点事件发布),实际上这个可以做到,但是要做好并不容易,用得不好很容易导致如操作野指针的问题,Delphi和C#还是有一个根本的差异性问题。我记得在官网上发布的一份网友写的Source,里面就有一个类可以使用(实际上我自己也实现过这样一个类,只是没有他写得那么通用)。个人还是建议在需要用时去实现和使用,在很多时候这都不是必要的。理由在于,Delphi并没有完全遵守Windows消息的规则,如果是完全遵守消息规则,对于这些事件全以消息进行广播的话,一切都可以很好地解决,但是Delphi是直接调用函数的,对于类函数来说,函数体只是一个需要带上Self指针调用的程序代码段,从而在调用时并没有对对象进行“存在性”检查,这就导致了,即使是有野指针的存在也难发现。如果再把这一切都用一个容器做处理的话,结果就会使得一个使用概论不到万分之一的功能被冗余设计,由此带来的问题,不管是性能问题还是逻辑设计难度问题,都是非必要的。
      

  24.   

    官网上的叫“multicast_events_framework_for_delphi_win32”
    Delphi.about.com当中也有个不错的解决方案:http://delphi.about.com/od/usedbvcl/a/multicastdelphi.htm
      

  25.   

    当前组件大多是基于PME模型的. 尤其在GUI上提供了很大的灵活性. 但我总觉得一开始就在ONXXX事件中写代码.
    方便是方便了,但让人忽略了很多设计方面的东西.(先说下我的一个习惯. 如果能用一行代码解决问题,我绝不写两行代码)
    所以提C#中的 Click += XXXX.Click 代码, 是因为在delphi中,我要多写些代码(不管用观察者模式(大才小用)
    还是其它方式,都要引用不必要的类或方法,使一个简单的问题反而搞的复杂了)
    {-- 尤其像TDataSet的子孙们根本就不应该在属性编辑器中有OnXXXX事件. public出来就OK了. --}
    我觉得把像一些 if .. then 的代码写在 OnBeforeDelete OnAfterPost...等事件里是有问题的.不知道大家怎么看.{-- 或者TDataSet的子孙根本不应该能直接拖到TForm 或 TDataModule 上. --}
    TDataModule一建立, 一大堆DataSet什么的就都生成了.浪费内存不说. 如果上面的TDataSet多了, 看着眼晕.
    找起来眼花. 另外很自然的, TDataModule单元中一大堆OnXXXX. (我刚用DELPH的时候就是这样.所以我这么说.)
    如果TDataSet的子孙们不能直接拖上去. 我想每个人都应该有自己的"套路"了吧. 并且或许会想的更多一些.
      

  26.   


    楼主可以考虑去找Borland或CodeGear索要赔偿,当然你需要准备一份正版Delphi和神经受损的证明。
      

  27.   

    {-- 或者TDataSet的子孙根本不应该能直接拖到TForm 或 TDataModule 上. --} 
    TDataModule一建立, 一大堆DataSet什么的就都生成了.浪费内存不说. 如果上面的TDataSet多了, 看着眼晕. 
    找起来眼花. 另外很自然的, TDataModule单元中一大堆OnXXXX. (我刚用DELPH的时候就是这样.所以我这么说.) 
    如果TDataSet的子孙们不能直接拖上去. 我想每个人都应该有自己的"套路"了吧. 并且或许会想的更多一些. --------------------RAD的开发模式问题,其实就是工具摆在这了,看大家怎么用了。从来不喜欢在DATASET上写事件的飘过...
      

  28.   

    虽然不是从delphi 1.0开始用, 即使现在jave, c#很火.但每想到当初borland能推出delphi. 仍然要赞一下!!看"女人"多了,难免会和"老婆"比较比较. 可老婆毕竟是老婆. 在心里替换不了.
      

  29.   

    delphi里不是还有个sender可以用作通知吗
      

  30.   


    这里貌似有两个问题,第一个是ONXXXX,第二个是多路通知事件。对于第一个问题俺完全不能理解……所谓时间也就是一个回调函数的问题。一个类的回调函数可以允许开发者在不继承这个类的情况下改变这个类的行为,其实也就是一种变相的派生类的方法(Windows也有所谓的子类化,搞的是一样的事情)。之所以弄成published而不是public,也是为了大家写代码方便些,更重要的是让用户在不打开类库源代码的情况下清楚的知道他能做什么。个人觉得这个绝对是Delphi的一大创举和亮点(此处用过去时T_T)。第二个问题,Delphi不支持多路事件是一个遗憾,估计是实现的成本有点高,而且有时候反而降低了系统的编译和运行效率。
      

  31.   

    我想LZ的意思是不是主要想告诉我们,要多用sender as?
      

  32.   

    我记得Java里也可以使用委托代理,但是他明确警告你了,记得好像是说不保证调用顺序,不太清楚了,因为觉得用处不大。
    且,委托代理估计大多都是使用Hash表,所以保证了效率和空间就不保证调用顺序了。
    估计CSharp也差不多。当多个Click事件都要操作同一数据时就不太妙了,你要自己保证数据的正确性,那时候恐怕更麻烦。
    如果你非要用代理,干脆用TList建立一个事件列表,然后在一个事件(a)里依次调用它们,我个人觉得这和委托没什么两样,然后,把a赋给OnClick。这不就一样了!当然,如果你对事件列表排序了的话,那调用顺序也是无法保证的。
      

  33.   

    支持楼主。
    支持liangpei2008
    Delphi中保留了很多“面向窗体”的特征,让人感觉不够完美。
    不能显示的控件就不应该搁到窗体上。
      

  34.   

    控件,或者在这里应该称之为组件更为准确,用于组合功能的单元部件。设计期的拖放功能不是针对窗体,而针对组件容器(Component Container)提供了一个可视化的操作UI。所以向乎任何组件(Component)都可以被“拖-放”操作。而组件可以从功能上划分为若干类,比如根据运行期是否带有UI就可以分出可视化组件和非可视化组件。不要光看到Form支持拖放,还有如DataModule,Service等都支持,后两者都非运行期可见的。
      

  35.   

    嘿嘿,你真的用了多长时间的Delphi啊?真的用了很长时间么?如果你觉得Published不好,可以覆盖掉么。
    创建一个子孙,覆盖掉你希望隐藏或覆盖的东西不就行了,他顶多提示你,你改变了访问权限,不会影响程序的编译,当然,如果你再在其它地方又希望以Published方式调用而导致出错,那就另当别论了。Published是为了便于你了解和使用,但因为他方便你就搬石头砸自己脚那就不优雅了吧?再说了,Delphi并没有要求你必须要把组件拖放到容器中才能使用吧?你完全可以在代码中自己声明自己创建然后自己使用啊!还有,一定要记得自己的,还要自己擦屁股,必须自己去释放用完的组件。就像C/C++和Java那样,你完全可以不使用拖放来编写程序啊!
    完完全全没有人会阻止你这么去做的呀!
    我就经常嫌放在窗体里的非可视组件太多,而觉得太乱,就在代码中自己声明,并创建,当然,要自己记得对单元引用的添加和声明(当然,拖放就不用担心单元引用的添加和变量声明了),然后使用和释放。但是有时过段时间我再回头来看这段代码却还是觉得组件放在明处(窗体上)更亲切和容易理解。“支持楼主。 
    支持liangpei2008 
    Delphi中保留了很多“面向窗体”的特征,让人感觉不够完美。 
    不能显示的控件就不应该搁到窗体上。 ”不是Delphi把你束缚在"面向窗体"中,是你自己把自己束缚在其中了。不能显示的组件或控件,你完全可以不在窗体上放置么,根本就没有人会阻止你去这么做。我们往往把自己的愚蠢归咎于工具的糟糕,其实,这才是我们最可悲的地方。
      

  36.   

    to 66楼:属性覆盖可见性只能由低往高,published的属性是不能被覆盖回public的
      

  37.   

    你喜欢给自己找麻烦,喜欢在很乱的窗体和自己动态创建本不需要动态创建的组件这两者之间二选一,这是你的爱好,但并不能说这不是一种缺陷。
    其他工具中有缺陷,也并不能说这不是Delphi的一个缺陷。
      

  38.   

    type
      TForm1 = class(TForm)
        Button1: TButton;         //Button对象
        procedure Button1Click(Sender: TObject);
        procedure FormCreate(Sender: TObject);
      private
        FXXXObject: TXXXObject;   //XXX对象
      public
        { Public declarations }
      end;var
      Form1: TForm1;implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
    begin
      //Form自己造个房间来, 让Button.onClick指向这个房间.
      //Button和XXXX对象或其它对象通话. 
      //弄个List也好还是其它办法也好. 还要再写代码.
    end;procedure TForm1.FormCreate(Sender: TObject);
    begin
      //C#中可以这样
      Button1.Click += XXXX1.Click; //在这你自己通话吧. Form不管了.(也不用造房间了) 
      Button1.Click += XXXX2.Click  
      ... end;Form作为一个中介者, 知道很多"对象". 本身复杂度就高. 还要自己造个房间.(没事给自己找事)事件本身是好的, 至少可以让对象间解耦,不需要知道是谁关心自己的事件.
      

  39.   

    为什么要在Form上造?为什么不在你的Button1当中实现?你完全可以建议一个
    TYourButton = class(TButton),然后建议自己的事件订阅和发布机制。
      

  40.   

    所有这些都是人造出来的,只是一个是别人造的,一个是自己造的。任何一个人在设计的时候都会考虑到它的用户群体当中的适用性。如果某一项需求超过了10%的用户需求量,我估计就有可能被设计者考虑,但是如果用户需求量只是百分之一甚至更少,那就要问一个必要性了。冗余设计没有不对,但是绝对不是提倡的,特别是隐性弊端远大于价值的时候,这个设计就只能交给需要的用户自己去设计。没有任何绝对说是被拖到Form上的Button2,Button3不可以被中余释放掉,那么我前面已经提到过如果你没有一种很好的机制进行处理,势必会造成野指针访问等等不必要的麻烦,而这并不是设计者所想要的。难道需要用一个不足1%的人使用的功能,然后去约束可能远远超过20%的人使用该功能?或者还是给出大量的警告?顺便问一句在这里看贴子的各位,有多少人不是只管编译通过,而很仔细地注意编译时生成的种种Warning的?
      

  41.   

    很仔细地注意编译时生成的种种Warning +1不过这个好像和论题无关- -
      

  42.   

    我的本意是阻塞或者封闭Published属性,然后自己实现;当然,我也发现了我的表达是不恰当的。但仔细想想,发现自己的想法也很可笑,Published和Public的区别就是RTTI而已。只是我依旧不太明白楼主的意思,如果不喜欢在Inspector中操作,那也完全可以在代码中赋值。还是因为不喜欢Delphi的RTTI,因为它容易被反编译识别呢?
      

  43.   

    双击Form上的button时, 会自动生成 procedure Button1Click(Sender: TObject);
    这个方法不是Button的, 而是Form, 本身是button的事. Form也不得不参加进来自己加入一个方法. 觉得是可以推敲的.如果没有足够的理由,一般不会创造MyButton或其它控件. 就个人来说,觉得VCL的设计的非常棒,弹性很大. 所以通常是建个ButtonHelper的类来处理. 
      

  44.   


    之所以觉得不应在属性编辑器上有很多的ONxxx事件. 就是觉得 Form, DM或其它(好像也没什么了)会加入大量的方法. 并且生成的这些方法会被随便使用. 其实这个问题本身来说并不能怪到DELPH上,毕竟用工具的是人.
      

  45.   

    warning在很多时候是:我(编译器)允许你这样子写代码,但是我需要给你一定的提醒,这样子使用可能会存在什么问题,会有什么后果。事件的多路发布可以是两种情况:
    1.不依赖其它实例的多路发布,即链式的多次回调通知,这个相对比较简单,其实就是允许同一个事件允许有多个处理例程,对于这个,跟你在Button1Click当中再去调用一个Button2Click,Button3Click...没有任何区别。
    2.依赖其它实例的多路发布,这个就会存在一个问题,对于C#并不存在野指针的问题,所以不需要担心,任何时候依存关系都被维持着,但是Delphi/C++则似乎并不是这么简单的。这个就类似在Button1Click当中去调用Button2.Click,Button3.Click...这跟前者是完全不一样的。但是实际上这两种都有人需要,就TButton.OnClick而言,这两种处理上是完全不同。如果你是设计者,你会如何考虑?
      

  46.   

    事件的多路发布可以是两种情况: 
    1.不依赖其它实例的多路发布,即链式的多次回调通知,这个相对比较简单,其实就是允许同一个事件允许有多个处理例程,对于这个,跟你在Button1Click当中再去调用一个Button2Click,Button3Click...没有任何区别。 
    2.依赖其它实例的多路发布,这个就会存在一个问题,对于C#并不存在野指针的问题,所以不需要担心,任何时候依存关系都被维持着,但是Delphi/C++则似乎并不是这么简单的。这个就类似在Button1Click当中去调用Button2.Click,Button3.Click...这跟前者是完全不一样的。
    不是很明白, 僵哥能否再详细的说下这两种方式.(尤其是第二种.)
      

  47.   


    其实,就像你不会直接使用TForm一样,你都会生成一个TForm的子类,其实你也可以先子类化一个组件,然后加到你的Form中,但调用时会需要大量参数。就是用VC不也是把消息在类中以函数来实现的么?C#也是在类中以函数来实现吧。正因为它是你的Form的函数,所以你才能操作其中的各种数据和组件啊!想象一下,喔哦,那需要传递多少参数
    一个没有接口的类...用都没法用,谁又会知道他的存在?
    我有时也会一时钻牛角尖,可能你也处在此刻。
      

  48.   

    嗯,我知道WARNING是这个作用,我只是说具体到这个论题上而已。
      

  49.   

        搞了多年的Delphi看来我也仍然是入门级,楼主的这些想法的确有可圈可点之处,入了Mac开发的道,总在使用xCode开发,有些开发机制与楼主说的似乎异曲同工。
         
         编码与界面完全分开,至于界面中的控件采用IBOutlet进行联系,方式则是与任意IBAction(方法)进行连接,对于楼主提出的方法代理,的确是个可以灵活运用的机制,关于数据代理部分却与楼主说得十分相似,没有任何控件,直接是代码上的连接,不过是否适合刚入门的人就不得而知了,毕竟都是从磕磕绊绊中走过来的。
      

  50.   


    我觉得僵哥的意思是,
    第一种是不依赖于特定对象是否存在的方法调用。即,即使对象不存在也不影响程序正常运行的方式。比如,你创建了Button2的OnClick事件——Button2Click,但是,在Button1的Click事件调用它之前,Button2被释放了,但Button2Click依然存在,此时,你依然可以调用Button2Click例程。
    第二种是必须依赖于特定对象的存在,及如果Button2的实例对象不存在那就根本不存在Button2.Click属性。则此时调用它就会出错。
      

  51.   


    1、“有些非可视的组件,尤其像TDataSet的子孙们根本就不应该在属性编辑器中有OnXXXX事件. public出来就OK了. 
    或者TDataSet的子孙根本不应该能直接拖到TForm 或 TDataModule 上”  
    这是IDE中所谓可视化设计的思想。就可视化设计IDE来说这并不存在多大问题。RAD中嘛,拖一个TComponent子类放界面上就可以直接用,比你手工uses单元,实例化其对象会快很多。2、“TButton.Click. 应该能像C#这样 Click += XXXX.Click会更好” 
    完全一个东西,都是函数指针。只不过Delphi面世的时候,程序在大多数时候还不需要一个事件需处罚多个处理过程,新出来的C#可以对一个事件存储多个函数指针而已
      

  52.   

    两者有区别也有一定的联系,delphi封装的东西自然有它的道理,相比较C#更强大一些。
      

  53.   


    希望您搞清楚一个基本的逻辑:
    Button被点击这是“button的事”,但是Button被点击之后要做什么(“这个方法”)并非“button的事”,至少在大多情况下Button被点击之后的事件处理与这个Button本身没有什么关系。
    您认为Button被点击的事件处理方法就“应该”属于Button这恰恰是把代码和界面元素混为一谈的拙劣设计。Button只应该起通知的作用,它不必、也不应该管被点击之后做些什么。VCL的设计当然是非常棒的,而且它恰好没有棒到您期待的那种程度。
    恕我直言,对于一个应用框架“应该”如何构造,您还没有一个清楚的概念。指点江山为时尚早。:)
      

  54.   

    做C#的哥们,以前就是做Delphi的哥们;
    东西都是一个人发明的;
      

  55.   

    to trazom:这又有点过分了,事件还是很重要的,尤其在异步机制中。关键是否在合适的地方使用而已。
      

  56.   


    可不是一个人哦。
    C#的设计者anders hejlsberg在Borland的时候主要是做编译器的,VCL架构的设计者是chuck jazdzewski。说句题外话,Borland的四大高手ABCD(anders hejlsberg、blake stone、chuck jazdzewski、danny thorpe)都跑了,Borland居然不倒,也算得上是超级厉害,和以前的仙童公司有得一拼,是(别人的)技术摇篮。
      

  57.   


    希望您搞清楚一个基本的逻辑:
    Button被点击这是“button的事”,但是Button被点击之后要做什么(“这个方法”)并非“button的事”,至少在大多情况下Button被点击之后的事件处理与这个Button本身没有什么关系。
    您认为Button被点击的事件处理方法就“应该”属于Button这恰恰是把代码和界面元素混为一谈的拙劣设计。Button只应该起通知的作用,它不必、也不应该管被点击之后做些什么。VCL的设计当然是非常棒的,而且它恰好没有棒到您期待的那种程度。
    恕我直言,对于一个应用框架“应该”如何构造,您还没有一个清楚的概念。指点江山为时尚早。:) //----
    太高抬我. 指点江山本人是差的太远了. 不过我还是可以说出我个人的看法. 是不是. :)
    Button被点击这是“button的事”,但是Button被点击之后要做什么(“这个方法”)并非“button的事”,至少在大多情况下Button被点击之后的事件处理与这个Button本身没有什么关系。
    您认为Button被点击的事件处理方法就“应该”属于Button这恰恰是把代码和界面元素混为一谈的拙劣设计。Button只应该起通知的作用,它不必、也不应该管被点击之后做些什么。//--------
    "您认为Button被点击的事件处理方法就“应该”属于Button"
    这个是您的认为. 我只能说您未明白我想说的意思. Button要通知谁. 为什么不能直接通知过去呢. 偏偏要Form
    生成个buttonClick事件, 
    您觉得是直接  Click += XXXX.Click  好, 还是在form.buttonClick中写  XXXClick 好呢? 
      

  58.   

    哎,C#允许运算符重载,所以可以事先再Button的类定义中重载“+=”这个运算符的定义,所以你可以那么去做。
    其实质大体和调用一个事件列表相似,你完全可以自己订制一个Button类,来实现类似的方法,当然,实现起来可能会有很多需要考虑的元素和方面,毕竟,我们很难和那些天才的架构设计大师们相比。
    其实"+="运算符的重载也可看成一个函数,这和你用一个例程实现由有什么区别?
    区别就在于,C#中,已经在它的类体系里给你预定制了,而你想在诞生在C#之前的Delphi中使用它当然只能由你自己来实现整个体系了。
    打一个恐怕不太恰切的比喻,比如我有一台1968年的野马跑车,现在我非要在它上面安装ABS、GPS定位、车载DVD、车载卫星电视、倒车镜头、车载5.1音响系统和自动排档系统,显然,汽车生产厂家不可能给我提供该服务,我只能自己定制。我觉得这就很像楼主现在在说的这个话题。我个人觉得C#不想门语言,它更像微软的一个战略,一个可以用来消灭Window平台上其他应用开发竞争对手的战略。当然,我觉得箭头直指的是Java,同样,如果能顺便消灭其他所有对手就更好了。
      

  59.   

    第二种方式Button2.Click调用时,实际上它不是由Button2Click这样一个过程触发的,而是由一个TButton内部的调度去触发,在这种情况下,实际上走了一个相对要复杂一点的流程,如果设计当中进行了某些修改,比如重写Click处理例程,那么很有可能就不再是调用的Button2Click.其实在这种情况下形成的一种设计就完全有别于直接调用Button2Click,直接调用Button2Click的设计是对当前设计者可见的,而对Click过程的调用,由完全取决到实现Click处理例程的设计者.此时一旦Button2这个实例与Button1实例的绑定关系(显式的或者隐式的)被解除,那么这个预期对Button2.Click过程调用的处理,就会变成一个陷阱,并且这也不是设计TButton.Click这个过程的设计者所期望的,并且这种绑定更不是用户所预期的.Delphi和C#有太多的差异,我相信C#为了设计出这样一个Delegate(s),不仅仅只是为了让你点一个Button就可以连环触发多个Button的事件,只是它的设计当中支持类似的用法.C#本身应该算是一个高度封装的设计,它很棒的是,首先就解决了前面所提到的Button2这个实例的生命周期问题,它已经不再需要对Button1和Button2进行捆绑.于是我们前面担心的问题都不存在.换句话说,如果你要在Delphi当中实现一个Delegate也是可以的,但是你必须解决可能存在的众多问题,否则只能进行约束性使用.
    从设计的清晰度来讲,Button的OnClick本身就只是一个事实,它不应该去做更多累赘的事.做为一个闹钟的设计者,永远不会说是直接就设计出无数个闹铃接口.如果你想要得到更为广泛的通知服务,实际上在更多的时候提升闹铃的影响面,而不是为每一个人去提供一个闹钟.你也可以去设计另外一种更实用的通知服务,但是不能说原本闹钟的设计就是一个失败的设计.
      

  60.   

    to 95 楼:是“指点江山”还是“个人看法”,不过是一种说法,您不必介意。您说我未明白您说的意思,那您到底是什么意思呢?
    看您的原话“双击Form上的button时, 会自动生成 procedure Button1Click(Sender: TObject);这个方法不是Button的, 而是Form, 本身是button的事. Form也不得不参加进来自己加入一个方法. 觉得是可以推敲的. ”我相信任何思维正常的人都只能把您的意思理解成“Button被点击后的事件处理方法应该属于Button(‘这个方法’应该是Button的方法,不应该是Form的方法)”,您难道还要说“中文的语法是不是害了不少人”?您所谓“Button要通知谁. 为什么不能直接通知过去呢”令人费解,如何“直接通知”啊?Form.ButtonClick不是“直接通知”,XXXX.Click就是“直接通知”?恕我眼拙,我看不出来Click += XXXX.Click如何就比Button.OnClick := Form.ButtonClick更“直接”。唯一的差别不过是可以添加多个事件处理方法(挂接)还是只能设置单个事件处理方法(替换)//这个可以另外讨论。
    显然,您给出的这个XXXX.Click也不可能是孤立存在的,在面向对象的结构中它总得是某个对象(XXXX)的方法吧,不可能成了全局过程吧。您为什么非要看到它属于Form就不爽呢?(而且您不爽错了,见下面)最重要的一点,您说的“偏偏要Form生成个buttonClick事件”是明显的错误理解,就象我前面说的“对于一个应用框架“应该”如何构造,您还没有一个清楚的概念”,OnClick是一个事件,它是属于Button的,而Form生成的buttonClick是一个方法,是处理Button被点击之后要做的事,它是事件处理,而不是事件本身,因此它不必、也不应该成为Button的方法!
    就如同交通事故发生后的处理应该是交警的事,而不应该是交通事故中的车辆(司机)的事,那不乱套了。
      

  61.   

    换句话说,如果当初Delphi的设计者就把TButton.OnClick的通知增加一个通知列表,然后第一个触发都要从列表当中一个个找出来去通知.并且在99%的情况下,列表里面都仅有一个成员,你会做何评价?那为什么又不说C#的这种设计不合理呢?因为在C#当中所有这些都是Object,包括EventHandle,在它的设计概念当中就已经容允了这一切的存在.不要看button1.Click += new System.EventHandler(this.button2_Click);  这样一条简单的代码,实际上包含了很多的设计逻辑在里面.而实际上最终还是只完成了为Button1增加一个事件处理例程列表,而不是仅支持单一事件处理例程的设计.其实说白了,楼主举的例子就只是完成:就这么简单的一件事,却把它推给框架的设计者,个人觉得真的很不妥。