不管了MSDN上的例子 还是C#高级编程里的例子 都看了下...
感觉为什么一定要使用委托呢?正常的方式去调用类里另外一个方法不是一样么?
如果你要说可以多次new委托,达到复用?那么代码量没有减少,性能会有提升?什么样的情况下我需要使用委托或者匿名方法?
拿eventhandler来说,我初步的理解它也就是一个参数是sender和e的方法
比如我这样的代码:        public void Init(HttpApplication application)
        {
            application.BeginRequest += (new EventHandler(this.Application_BeginRequest));
            application.EndRequest += (new EventHandler(this.Application_EndRequest));
        }        // Your BeginRequest event handler.
        private void Application_BeginRequest(Object source, EventArgs e)
        {
            //do something;
        }        // Your EndRequest event handler.
        private void Application_EndRequest(Object source, EventArgs e)
        {
            //do something;
        }
我完全可以不那样写啊,我简单的写成如下形式不一样的意思吗?        public void Init(HttpApplication application)
        {
            application.BeginRequest += Application_BeginRequest();
            application.EndRequest += Application_EndRequest();
        }        // Your BeginRequest event handler.
        private void Application_BeginRequest(Object source, EventArgs e)
        {
            //do something;
        }        // Your EndRequest event handler.
        private void Application_EndRequest(Object source, EventArgs e)
        {
            //do something;
        }
上面的代码只是说明一下我的意思,不要深究里面的错误...我的意思就是说我完全可以在Init事件里去掉我要用的方法,而不使用委托
所以回到这个问题
什么样的情况下我需要使用委托或者匿名方法?

解决方案 »

  1.   


    这个代码的意思不是在Init里面调用Application_BeginRequest和Application_EndRequest方法,而是在
    开始请求的时候再调用Application_BeginRequest,结束请求的时候去调用Application_EndRequest        public void Init(HttpApplication application)
            {
                application.BeginRequest += (new EventHandler(this.Application_BeginRequest));
                application.EndRequest += (new EventHandler(this.Application_EndRequest));
            }
      

  2.   

    嗯,事实是很多时候,你要使用的方法并不确定
      抄袭某位前辈的代码
        假设有和欢迎的函数,你想使它在中国用户使用的时候用中文问好,在老外使用的时候用E文问好 如果不使用委托,你要编写两个函数
       
       static void welcome()
       {
         welcomeInChinese();
      } 
       或者
        static void welcome()
        {
         welcomeInEnglish();
        }
       static void  welcomeInChinese()
      {
        Console.WriteLine("欢迎您的使用");
      
      
      }
       static void  welcomeInEnglish()
      {
         Console.writeLine("Welcome to use!");
      }  嗯,如果这样的话,你的代码的适应性就很差,至于为什么··请看下面
       
       假如我们定义一个委托
         delegate void myDel(); //委托是一个类,委托的变量是方法.
        
         修改前面的欢迎函数定义 
          
           static void welcome(myDel a )
          {
             a();
          }     当遇见老外的时候,就把 welcomeInEnglish 这个变量(额,就当他是变量吧)传给a,如果是中国人,就传
    welcomeInChinese .
          
         这样代码的适应性就很强了。
          至于为什么?
          很简单,假如你不使用委托,你如何实现动态的调用不同的函数来服务不同的客户? 除了直接修改代码,你还能做什么?
        用了委托,你就可以动态的调用函数,而不需要去修改代码了
         用个if就行
       if(中国客户)
       {
        welcome(welcomeInChinese) ;//委托变量存储的是方法
        
       }
      else
       {
        welcome(welcomeInEnglish);
       }
       
     
      

  3.   

    看来你完全没有理解委托...你的第二种写法只是Lambda的语法糖,叫做匿名委托...还是委托,换汤不换药...委托是给其他调用者使用的,它的最大特点是调用者不知道什么时候该调用它,所以只好提前订阅它然后做自己的事不去管它...当委托对象有了订阅者感兴趣的消息就会通知调用者...这是方法不能很容易做到的...想象一下订阅报纸或牛奶的过程...去看看Windows消息机制和事件驱动机制将有助于你理解委托...
      

  4.   

    我没说在Init里调那2个方法,我的意见是application.BeginRequest 内调用Application_BeginRequest;application.EndRequest 内调用Application_EndRequest ....
    既然我要给BeginRequest加上一个动作(方法),那么我在这个BeginRequest方法内调用我要用的即Application_BeginRequest不是一样么?
      

  5.   

    这个好像也不是很确切的能说明问题啊
    这样写是一样实现功能,但是为什么要这么复杂的写呢?
    直接if(中国客户) 
      { 
        welcomeInChinese() ;    
      } 
      else 
      { 
        welcomeInEnglish(); 
      } 
    ...省一个delegate 省一个welcome()......囧......
    搞不懂了...查了下资料说在设计大型应用程序时使用委托和事件可以减少依赖性和层的关联...
    不知道是否有人在实际项目中使用过委托,那么是在何种情况下让你使用委托的....
      

  6.   

    能据个例子吗?在什么事件里订阅不就是在什么时候(订阅者被执行?如上面的application.BeginRequest被执行时)调用吗?显然是确定的啊...能否稍微详细点讲一下...
      

  7.   

    找了个例子,一起学习:
    重点是在调用的时候要实例化,指定这个delegate 要做什么事情。
    delegate 参数知道结果是什么样的就等了。这样做的话好处是
    1.在执等的时候可指定给什么方法,代码比较好看,重用比较好。比如我要有一个降XU,只要传一个委托参数,不用再写static public void SortJianXUusing System;
    namespace BubbleSorter
    {
      delegate bool CompareOp(object lhs, object rhs);  class MainEntryPoint
      {
        static void Main()
        {
          Employee [] employees =
                {
                  new Employee("Bugs Bunny", 20000),
                  new Employee("Elmer Fudd", 10000),
                  new Employee("Daffy Duck", 25000),
                  new Employee("Wiley Coyote", /*(decimal)*/1000000.38m),
                  new Employee("Foghorn Leghorn", 23000),
                  new Employee("RoadRunner'", 50000)};
          CompareOp employeeCompareOp = new CompareOp(Employee.RhsIsGreater);
          BubbleSorter.Sort(employees, employeeCompareOp);      for (int i=0 ; i<employees.Length ; i++)
            Console.WriteLine(employees[i].ToString());
          Console.ReadLine();
        }
      }  class Employee // : object
      {
        private string name;
        private decimal salary;    public Employee(string name, decimal salary)
        {
          this.name = name;
          this.salary = salary;
        }    public override string ToString()
        {
          return string.Format(name + ", {0:C}", salary);
        }    public static bool RhsIsGreater(object lhs, object rhs)
        {
          Employee empLhs = (Employee) lhs;
          Employee empRhs = (Employee) rhs;
          return (empRhs.salary > empLhs.salary) ? true : false;
        }
      }  class BubbleSorter
      {
        static public void Sort(object [] sortArray, CompareOp gtMethod)
        {
          for (int i=0 ; i<sortArray.Length ; i++)
          {
            for (int j=i+1 ; j<sortArray.Length ; j++)
            {
              if (gtMethod(sortArray[j], sortArray[i]))
              {
                object temp = sortArray[i];
                sortArray[i] = sortArray[j];
                sortArray[j] = temp;
              }
            }
          }
        }
      }
    }
      

  8.   

    可能是便于系统的封装吧,就像button的Click事件,我们通常写的都是事件的处理过程,还有很多代码是系统的~~
      

  9.   

    .net中的委托可以被当成c++里面的回调函数(参考Array.Sort方法和Interop时的回调函数的处理),
    也可以被当成java等里面的观察者(参考事件),
    而且在很多需要跨越上下文的调用是都必须使用委托(参考Thread.Start方法)另外,委托也可被用来在线程池里面执行某个方法(参考BeginInvoke和EndInvoke方法),
    以及由于委托的性能接近于调用虚方法的执行效率,可以被当作动态生成的方法的最好载体(参考DynamicMethod.CreateDelegete方法)
      

  10.   

    委托可以简单看成是一个封装了的会自动增长和缩短的托管函数指针列表
    ->A
      B
      C
      ...
    主要用在子线程操作主线程UI控件和作为回调函数
      

  11.   

    这里我有一点不成熟的分析
    http://topic.csdn.net/u/20081001/13/f581fa25-b929-4739-9fa0-84d65e5c49ee.html
      

  12.   


    在运行时你不一定知道外面会提供哪个方法(函数), 不是在内部假定调用哪个, 而是调用一个符合约定的函数就行,
    约定就是通过 delegate 来描述的, 也就是 C++ 里头的函数指针, callback,
    而外部实现的函数可以通过 delegate 实例的方式传递进来// 定义一个用于比较两个对象的函数原型(delegate)
    // op1 > op2 返回 大于 0 的数
    // op1 = op2 返回 0
    // op1 < op2 返回小于0的数
    delegate int comparehandler(object op1, object op2);// 函数参数为一个 comparehandler 实例, 也就是一个具体的函数实现
    // 不管球它是哪个类的哪个函数, 只要符合 comparehandler 的签名(signature)就行
    void somefunction(comparehandler ch)
    {
        //..
        // 对函数内部对象 object1 , object2 比较
        // 这里不管具体实现, 运行时可以传递任意实现来玩耍
        int result = ch(object1, object2);
    }
    当编写基础代码时, 这样的范式很常用, 有时需要一个功能, 但由于某种原因, 在模块内不能实现时, 
    就可以采用这种参数化的方式.
      

  13.   

    一、委托   
      委托类似于函数指针,但函数指针只能引用静态方法,而委托既能引用静态方法,也能引用实例方法。   
        
      委托使用分三步:1、委托声明。2、委托实例化。3、委托调用。   
      例程一:   
      using   System;   
        
      namespace   委托   
      {   
          delegate   int   NumOpe(int   a,int   b);   //委托声明   
          class   Class1   
          {   
              static   void   Main(string[]   args)   
              {   
                  Class1   c1   =   new   Class1();   
                  NumOpe   p1   =   new   NumOpe(c1.Add);   //委托实例化   
                  Console.WriteLine(p1(1,2));   //委托调用   
                  Console.ReadLine();   
              }   
        
              private   int   Add(int   num1,int   num2)   
              {   
                  return(num1+num2);   
              }   
          }   
      }   
      例中,委托NumOpe引用了方法Add。   
      委托声明了以后,就可以象类一样进行实例化,实例化时把要引用的方法(如:Add)做为参数,这样委托和方法就关联了起来,就可以用委托来引用方法了。   
      委托和所引用的方法必须保持一致:   
      1、参数个数、类型、顺序必须完全一致。   
      2、返回值必须一致。   
        
      二、事件   
        
      事件有很多,比如说鼠标的事件:MouserMove,MouserDown等,键盘的事件:KeyUp,KeyDown,KeyPress。   
        
      有事件,就会有对事件进行处理的方法,而事件和处理方法之间是怎么联系起来的呢?委托就是他们中间的桥梁,事件发生时,委托会知道,然后将事件传递给处理方法,处理方法进行相应处理。   
        
      比如在WinForm中最常见的是按钮的Click事件,它是这样委托的:this.button1.Click   +=   new   System.EventHandler(this.button1_Click);按按钮后就会出发button1_Click方法进行处理。EventHandler就是系统类库里已经声明的一个委托。   
        
      三、自定义事件及其处理   
        
      EventHandler以及其它自定义的事件委托都是一类特殊的委托,他们有相同的形式:   
        
      delegate   void   事件委托名(object   sender,EventArgs   e);   
        
      object用来传递事件的发生者,比如二中的Button控件就是一个事件发生者;EventArgs用来传递事件的细节。   
        
      例程二:   
      using   System;   
        
      namespace   最简单的自定义事件   
      {   
          ///   <summary>   
          ///   事件发送类   
          ///   </summary>   
          class   Class1   
          {   
              public   delegate   void   UserRequest(object   sender,EventArgs   e);   //定义委托   
              public   event   UserRequest   OnUserRequest;   //定义一个委托类型的事件   
        
              public   void   run()   
              {   
                  while(true)   
                  {   
                      if(Console.ReadLine()=="a")   
                      {//事件监听   
                          OnUserRequest(this,new   EventArgs());   //产生事件   
                      }   
                  }   
              }   
          }   
        
          ///   <summary>   
          ///   事件接收类   
          ///   </summary>   
          class   Class2   
          {   
              static   void   Main(string[]   args)   
              {   
                  Class1   c1   =   new   Class1();   
                  c1.OnUserRequest   +=   new   Class1.UserRequest(c1_OnUserRequest);   //委托实例化后绑定到事件   
                  c1.run();   
              }   
        
              private   static   void   c1_OnUserRequest(object   sender,   EventArgs   e)   
              {//事件处理方法   
                  Console.WriteLine("\t你触发了事件!");   
              }   
          }   
      }   
      例程三:   
      using   System;   
        
      namespace   带事件数据的事件   
      {   
          ///   <summary>   
          ///   带事件数据的事件类,从EventArgs继承   
          ///   </summary>   
          class   OnUserRequestEventArgs:EventArgs   
          {   
              private   string   inputText;   
              public   string   InputText   
              {   
                  get   
                  {   
                      return   inputText;   
                  }   
                  set   
                  {   
                      inputText   =   value;   
                  }   
              }   
          }   
        
          ///   <summary>   
          ///   事件发送类   
          ///   </summary>   
          class   Class1   
          {   
              public   delegate   void   UserRequest(object   sender,OnUserRequestEventArgs   e);   
              public   event   UserRequest   OnUserRequest;   
        
              public   void   run()   
              {   
                  while(true)   
                  {   
                      Console.WriteLine("请输入内容:");   
                      string   a=Console.ReadLine();   
                      //if(a=="a")   
                      //{   
                      OnUserRequestEventArgs   e1   =   new   OnUserRequestEventArgs();   
                      e1.InputText   =   a;   
                      OnUserRequest(this,e1);   
                      //}   
                  }   
              }   
          }   
        
          ///   <summary>   
          ///   事件接收类   
          ///   </summary>   
          class   Class2   
          {   
              [STAThread]   
              static   void   Main(string[]   args)   
              {   
                  Class1   c1   =   new   Class1();   
                  c1.OnUserRequest   +=   new   Class1.UserRequest(c1_OnUserRequest);   
                  c1.run();   
              }   
        
              private   static   void   c1_OnUserRequest(object   sender,   OnUserRequestEventArgs   e)   
              {   
                  Console.WriteLine("\t你输入的是:"+e.InputText);   
              }   
          }   
      }   
      例程三跟例程二唯一的差别在于自定义了一个类OnUserRequestEventArgs,从EventArgs继承。
      

  14.   

    成熟的人做成熟的是,工程师应该解决工程问题,而学生才会变来变去地总是破坏他自己的代码。假设你写一个“我的日程表”的对象,你的日程可能在修改时通知客户它自己被修改了,你会变来变去地为每一个客户而改写这个日程代码吗?那么你不被认为是稳定可靠的合作者。你的代码是成熟的,意味着你的代码从来不需要修改,就能为任何客户做通知服务了!事件只是委托的稍微复杂一点的封装。从技术上说,你的日程通知客户,其接口的设计权利在于你,而不是在于客户程序。从应用上说,当你学习.NET时你无须去学java中盛行的什么云山雾罩的许多设计模式,搞清楚委托(和事件)机制就能发觉那些所谓设计模式纯粹是不懂委托和事件机制的人搞的繁琐设计。
      

  15.   

    委托是C#中新加入的一个类型,可以把它想作一个和Class类似的一种类型,和使用类相似,使用一个委托时,需要两个步骤,首先你要定义一个委托,就像是定义一个类一样;然后,你可以创建一个或多个该委托的实例。 
      

  16.   

     4楼说的对。后面的回复我都没有细看。
      第一种和第二种写法全部都是在注册委托(使得事件与具体的实现关联)。
      虽然没有写New EventHandler(),但是编译器已经能够自动识别函数的签名,然后发现与事件声明的委托签名相同,因此注册。
      后面.net的匿名类型、隐式转换也有些类似,就是说,你无需指定类型的签名,编译器已经可以自动去正确推测了.
      

  17.   

    实现异步操作时使用委托和事件的。
    与多线程编程中的异步方法原理一样,B在发送消息调用A提供的事件后,不必等待,可以接着处理自己的事情,等A的事件
    结束后,将结果通过消息传递给B。