zoukankan      html  css  js  c++  java
  • C# 委托和事件

    一、是什么

    1)委托包含对方法而不是方法名称的引用。使用委托可以在运行时动态设定要调用的方法,不知道方法名称,也可以调用方法,执行(或调用)一个委托将执行该委托引用的方法。

    2)委托将名称与方法的定义连接起来,即将方法的实现附加到该名称。这样便可以使用该名称调用特定的方法。但是,委托要求方法的实现和委托必须具有相同的方法签名(也就是说,他们应该具有相同数量/类型的参数),并有相同类型的返回值。

    3)委托更像一个具有通用的方法名称,在不同的情况将该名称指向不同的方法,并通过委托执行这些方法。

    二、怎么用

    使用委托包括三个步骤:

    1)定义委托

    2)实例化委托

    3)使用委托

    我们上一个例子:

    class Program  
    {  
        //定义一个委托  
        public delegate int Call(int num1, int num2);  
      
        class Math  
        {  
            public int Mutiply(int num1, int num2)  
            {  
                return num1 * num2;  
            }  
      
            public int Divide(int num1, int num2)  
            {  
                return num1 / num2;  
            }  
        }  
      
        static void Main(string[] args)  
        {  
            Call objCall;  
            Math objMath = new Math();  
            objCall = new Call(objMath.Mutiply);//实例化一个委托  
            
            int result = objCall(5, 3);//使用委托  
            Console.WriteLine("结果为 {0}", result);  
        }  
    }  

    值得说明是,

    objCall = new Call(objMath.Mutiply);//实例化一个委托  

    objCall = objMath.Mutiply; //直接给委托赋值

    这两种方式效果是一样的,只是两种不同的写法。用.net reflector反编译上述代码,会发现其实objCall = objMath.Mutiply最终还是会编译生成objCall = new Call(objMath.Mutiply)。

     上面的例子,我们再进一步,用匿名委托实现:

    static void Main(string[] args)  
    {  
        Call objCall = delegate(int num1, int num2) { return num1 * num2; };//匿名委托  
        int result = objCall.Invoke(3, 5);//使用委托  
        Console.WriteLine("结果为 {0}", result);//输出:结果为 15  
    }  

    我们还可以将:

    int result = objCall.Invoke(3, 5);//使用委托  

    替换为:

    int result = objCall(3, 5);//使用委托  

    效果是一样的。

     再进一步,用Lambda表达式进行简化,可以将:

    Call objCall = delegate(int num1, int num2) { return num1 * num2; };//匿名委托  

    替换为:

    Call objCall = (int num1, int num2) => { return num1 * num2; };//Lambda表达式  

    更简化一步,变为:

    Call objCall = (num1, num2) => { return num1 * num2; };//Lambda表达式  

    这就是C#委托的进化过程以及C#Lambda表达式对委托的支持。

     三、什么时候用

    1)委托类似于C语言中的函数指针,可以将方法作为函数的参数进行传递

    2)当不知道方法的具体实现时,就可以定义个委托,让它替我们干活

    3)我们在编程时用的最多的就是事件注册时使用。

    比如:

    this.button1.Click += new EventHandler(button1_Click);//button1注册Click事件 
    private void button1_Click(object sender, EventArgs e)  
    {  
        //方法具体实现内容  
    }  

    可以看到方法button1_Click作为参数传递给了EventHandler委托。

    再比如在线程方法中:

    Thread th = new Thread(new ThreadStart(Method));//这里的ThreadStart就是一个委托,里面可以直接传一个方法名Method,以委托的形式调用方法  
    th.IsBackground = true;  
    th.Start();  

     四、典型应用

    比如两个窗体Form1(一个文本框,一个按钮)、Form2(一个文本框,一个按钮)之间进行传值,Form1到Form2可以通过构造函数传值,但如果要将Form2的值传回给Form1该怎么办呢?这里就可以用到委托,这也是委托的经典应用场景之一。

     Form1.cs部分代码:

     private void button1_Click(object sender, EventArgs e)
     {
         Form2 form2 = new Form2();
         //通过public变量传值
         form2.text = this.textBox1.Text;
         //通过委托将子窗体的值传回主窗体
         form2.delegateShow = form2_ShowDelegateEventHandler;
         //通过注册事件将子窗体的值传回主窗体
         form2.ShowDelegateEventHandler += new Form2.ShowDelegate(form2_ShowDelegateEventHandler);
         form2.Show();
     }
    
     void form2_ShowDelegateEventHandler(string text)
     {
         this.textBox1.Text = text;
     }

     Form2.cs部分代码:

    public delegate void ShowDelegate(string text);//声明委托
    public event ShowDelegate ShowDelegateEventHandler;//声明事件
    
    public string text;//public变量
    public ShowDelegate delegateShow;//public委托变量
    
    private void Form2_Load(object sender, EventArgs e)
    {
        this.textBox1.Text = text;
    }
    
    private void button1_Click(object sender, EventArgs e)
    {
        //写法1:用事件
        if (ShowDelegateEventHandler != null)
            ShowDelegateEventHandler(this.textBox1.Text);
    
        //写法2:用委托
        delegateShow(this.textBox1.Text);
        this.Close();
    }

     五、总结

    1)委托是方法的签名,可以将委托作为方法的参数进行传递

    2)事件基于委托,或者说事件是特殊的委托

    3)委托可以用匿名委托简化代码(不需要再声明委托,然后实现),还可以用Lambda表达式进一步简化匿名委托(这也是C#推荐的方式)。

    代码下载:https://files.cnblogs.com/files/guwei4037/委托和事件窗体传值.zip

  • 相关阅读:
    DataGridView编辑后立即更新到数据库的两种方法
    DataTable 转换成 Json的3种方法
    C# 应用程序配置文件App.Config和web.config
    C#中使用JsonConvert解析JSON
    C#JsonConvert.DeserializeObject反序列化json字符
    WIN10远程桌面、常用命令
    control[控制面板]的参数
    win10企业版变成win10专业版的设置教程
    DLL加密
    微信小程序顶部tab
  • 原文地址:https://www.cnblogs.com/guwei4037/p/8084725.html
Copyright © 2011-2022 走看看