C#编程之委托与事件(一)

    xiaoxiao2026-05-10  3

    本文试图在 .net Framework 环境下,使用 C# 语言来描述委托、事件的概貌。希望本文能有助于大家理解委托、事件的概念,理解委托、事件的用途,理解它的 C# 实现方法,理解委托与事件为我们带来的好处。 C# 是一种新的语言,希望大家能通过本文清楚地看到这些,从而可以对委托、事件等技术进行更深入的理解和探索。   一. 委托 委托的本质   --在C#中,委托是一个特殊的类;   --在某种程度上,相当于C++的函数指针;   --在某种程度上,相当于接口(Interface); 委托的定义   --关键字:delegate   --public delegate void MyDelegate(string message);   注:在这里我们先了解一个概念,什么是函数签名?(在这里我不做过多解释,大家知道这个概念就行)。 使用委托   我们先来看看一个小的委托示例:   平时,如果说我们要设计一个做简单加减运算的方法,通常是怎么做的呢?看看下面代码:  1 class  Program  2      {  3        /// <summary>  4        /// 加法运算  5        /// </summary>  6        /// <param name="x">x</param>  7        /// <param name="y">y</param>  8        /// <returns></returns>  9        private static int Add(int x, int y) 10        { 11            int result = x + y; 12            Console.WriteLine("x + y = {0}",result); 13            return result; 14        } 15 16        /// <summary> 17        /// 减法运算 18        /// </summary> 19        /// <param name="x">x</param> 20        /// <param name="y">y</param> 21        /// <returns></returns> 22        private static int Sub(int x, int y) 23        { 24            int result = x - y; 25            Console.WriteLine("x - y = {0}", result); 26            return result; 27        } 28 29        static void Main(string[] args) 30        { 31            Add(88); 32            Sub(81); 33            Console.Read(); 34        } 35    }        上面的代码只要是学过程序的人都能看懂,也写得出,不过我们怎么通过委托来处理+,-运算呢?请看下面定义:  1 namespace  DelegateSample1  2 {  3    //定义一委托  4    public delegate int OperationDelegate(int x,int y);  5    public class Operator  6    {  7        private int _x, _y;  8        public Operator(int x, int y)  9        { 10            this._x = x; 11            this._y = y; 12        } 13 14        public void Operate(OperationDelegate del) 15        { 16            del(_x, _y); 17        } 18    } 19}   上面定义一个返回int类型需要两个int参数的委托。Operator里提供了一个操作方法带有一个委托参数。那通过委托怎么来处理这个简单的运算呢?好,现在我们来修改我们之前定义的主方法,如下:  1 namespace  DelegateSample1  2 {  3    class Program  4    {  5        /// <summary>  6        /// 加法运算  7        /// </summary>  8        /// <param name="x">x</param>  9        /// <param name="y">y</param> 10        /// <returns></returns> 11        private static int Add(int x, int y) 12        { 13            int result = x + y; 14            Console.WriteLine("x + y = {0}",result); 15            return result; 16        } 17 18        /// <summary> 19        /// 减法运算 20        /// </summary> 21        /// <param name="x">x</param> 22        /// <param name="y">y</param> 23        /// <returns></returns> 24        private static int Sub(int x, int y) 25        { 26            int result = x - y; 27            Console.WriteLine("x - y = {0}", result); 28            return result; 29        } 30 31        static void Main(string[] args) 32        { 33            //声明一个委托对象 34            OperationDelegate del = null; 35            del += new OperationDelegate(Add); 36            del += new OperationDelegate(Sub); 37 38            Operator op = new Operator(53); 39            op.Operate(del); 40            Console.ReadLine(); 41        } 42    } 43} 44    从上面的例子看,委托 OperationDelegate 代表了一组方法,他们的方法签名是:    --返回值:int; 参数:int ,int ;    只要符合该签名的方法,都可以赋给此委托:从上面不难看出,我要要创建一委托,则如下定义: 1 OperationDelegate del  +=   new  OperationDelegate(方法名);    从上面可以看到(+=)这个运算符,那是不是也有(-=)这个运算符呢?这就涉及到另外一个概念了--委托链。    --委托链:实际上委托实例就是一个委托链,+=代表增加委托实例到委托链中,相反-=则代表去掉该委托实例。 1 OperationDelegate del  =   null ; 2 del  +=   new  OperationDelegate(Add);  // 增加委托实例到委托链 3 del  -=   new  OperationDelegate(Add);  // 去掉委托实例到 委托的意义之一   --委托可以使得程序的复用程度提高;   --委托在一定程度上想当于接口;   例如:前面例子中的方法Operate(),由于接受的是一个委托类型;那么,我们可以对委托类型赋予不同的方法,来改变Operate()的性质。   我们在来看看另外一个示例:   --我们想输出一串数字,从0-100;   --对于输出的要求有三种;    -1、输出到控制台    -2、输出到窗体中的ListBox中;    -3、输出到文本文件中;   解决方案:   --使用委托和接口, 代码如下:  1 namespace  DelegateSample2  2 {  3    //定义一委托  4    public delegate void ShowNumberDel(object[] items);  5    public class ProcessNumber  6    {  7        private object[] items;  8        public ProcessNumber(int max)  9        { 10            items = new object[max]; 11            for (int i = 0; i < max; ++i) 12            { 13                items[i] = i; 14            } 15        } 16 17        public void ProcessItems(ShowNumberDel show) 18        { 19            show(items); 20        } 21    } 22} 23 在这里我们先把界面上的控件布局好并做好调用委托的准备工作,效果及代码如下:                      代码如下:  1 private  ProcessNumber pn  =   null ;  2 ShowNumberDel del  =   null ;  3  4 private   void  Form1_Load( object  sender, EventArgs e)  5 {  6     pn = new ProcessNumber(100);  7}  8  9 // 到控制台 10 private   void  ShowInConsole( object [] items) 11 { 12    foreach (object item in items) 13    { 14        Console.WriteLine(item); 15    } 16} 17 18 // 到ListBox 19 private   void  ShowInListBox( object [] items) 20 { 21    listBox1.Items.Clear(); 22    foreach (object item in items) 23    { 24        listBox1.Items.Add(item); 25    } 26} 27 28 // 到文本文件 29 private   void  ShowInFile( object [] items) 30 { 31   using (StreamWriter sw = new StreamWriter("Test.txt"true)) 32   { 33       foreach (object item in items) 34       { 35           sw.WriteLine(item); 36       } 37   } 38} 使用委托:  1 private   void  button1_Click( object  sender, EventArgs e)  2 {  3    pn.ProcessItems(new ShowNumberDel(ShowInConsole));  4}  5  6 private   void  button2_Click( object  sender, EventArgs e)  7 {  8    pn.ProcessItems(new ShowNumberDel(ShowInListBox));  9} 10 11 private   void  button3_Click( object  sender, EventArgs e) 12 { 13    pn.ProcessItems(new ShowNumberDel(ShowInFile)); 14} 15 16 private   void  button4_Click( object  sender, EventArgs e) 17 { 18    del += new ShowNumberDel(this.ShowInListBox); 19    del += new ShowNumberDel(this.ShowInFile); 20 21    pn.ProcessItems(del); 22} 完整的测试代码如下:  1using System;  2using System.Collections.Generic;  3using System.ComponentModel;  4using System.Data;  5using System.Drawing;  6using System.Text;  7using System.Windows.Forms;  8using System.IO;  9 10namespace DelegateSample2 11{ 12    public partial class Form1 : Form 13    { 14        public Form1() 15        { 16            InitializeComponent(); 17        } 18 19        private ProcessNumber pn = null; 20        ShowNumberDel del = null; 21 22        private void Form1_Load(object sender, EventArgs e) 23        { 24            pn = new ProcessNumber(100); 25        } 26 27        private void ShowInConsole(object[] items) 28        { 29            foreach (object item in items) 30            { 31                Console.WriteLine(item); 32            }             33        } 34        private void ShowInListBox(object[] items) 35        { 36            listBox1.Items.Clear(); 37            foreach (object item in items) 38            { 39                listBox1.Items.Add(item); 40            } 41        } 42        private void ShowInFile(object[] items) 43        { 44            using (StreamWriter sw = new StreamWriter("Test.txt"true)) 45            { 46                foreach (object item in items) 47                { 48                    sw.WriteLine(item); 49                } 50            } 51        } 52 53        private void button1_Click(object sender, EventArgs e) 54        { 55            pn.ProcessItems(new ShowNumberDel(ShowInConsole));              56        } 57 58        private void button2_Click(object sender, EventArgs e) 59        { 60            pn.ProcessItems(new ShowNumberDel(ShowInListBox)); 61        } 62 63        private void button3_Click(object sender, EventArgs e) 64        { 65            pn.ProcessItems(new ShowNumberDel(ShowInFile)); 66        } 67 68        private void button4_Click(object sender, EventArgs e) 69        { 70            del += new ShowNumberDel(this.ShowInListBox); 71            del += new ShowNumberDel(this.ShowInFile); 72            pn.ProcessItems(del); 73        }    74    } 75} 委托的意义之二    --在C#中使用线程需要用到委托     - Thread thread = new Thread(new ThreadStart(target));      -这里的ThreadStart就是一个委托,他的定义是:      -target既为符号ThreadStart委托的方法名;       --函数回调     -  当我们定义了一个委托;        public delegate void MyDelegate(int source);     -对于异步调用来说,就有BeginInvoke()和EndInvoke()方法;       - del.BeginInvoke(source, new System.AsyncCallback(CallBack), "test");     - private void CallBack(IAsyncResult asyncResult)       {             int result = del.EndInvoke(asyncResult);             //......       }   这里需要理解的就是什么叫函数回调?这个话题留给大家讨论,在此不作详细解说。关于委托本文只是入门级的文章,要想更详细深入的学习委托请查看具体的书籍或资料,本文就简单介绍到这里。 文中示例代码下载:Delegate.Event.Thread(1).rar
    转载请注明原文地址: https://ju.6miu.com/read-1309540.html
    最新回复(0)