关键词搜索

源码搜索 ×
×

C#委托和事件的使用实例

发布2020-12-09浏览344次

详情内容

使用委托时要先实例化,和类一样,使用new关键字产生委托的新实例,然后将一个或者多个与委托签名匹配的方法与委托实例关联。随后调用委托时,就会调用所有与委托实例关联的方法。
与委托关联可以是任何类或者结构中的方法,可以是静态方法,只要是可以访问的方法都可以。
参考视频 c#教程
1.创建一个委托类型使用关键字delegate(委托)

public delegate void DelegateChangeStart(string str);//创建一个实例
public class Program
{
    #region 定义方法
    static void TestWriteLine1(string str)
    {
        Console.WriteLine("这里是方法一:{0}", str);
    }
    static void TestWriteLine2(string str)
    {
        Console.WriteLine("这里是方法二:{0}", str);
    }
    static void TestWriteLine3(string str)
    {
        Console.WriteLine("这里是方法三:{0}", str);
    }
    #endregion
    static void Main(string[] args)
    {
        DelegateChangeStart EventChargeStartPan1, EventChargeStartPan2, EventChargeStartPan3;//定义委托变量

        //实现委托
        EventChargeStartPan1 = TestWriteLine1;
        EventChargeStartPan2 = TestWriteLine2;
        EventChargeStartPan3 = TestWriteLine3;

        //调用委托
        EventChargeStartPan1("1");
        EventChargeStartPan1("https://cdn.jxasp.com:9143/image/2");
        EventChargeStartPan1("3");

        Console.WriteLine("****************结束****************");


        Console.ReadLine();
    }
}

    在这里插入图片描述

    在这里插入图片描述

    2.一个委托实例,可关联多个方法:

    public delegate void DelegateChangeStart(string str);//创建一个实例
    public class Program
    {
        #region 定义方法
        static void TestWriteLine1(string str)
        {
            Console.WriteLine("这里是方法一:{0}", str);
        }
        static void TestWriteLine2(string str)
        {
            Console.WriteLine("这里是方法二:{0}", str);
        }
        static void TestWriteLine3(string str)
        {
            Console.WriteLine("这里是方法三:{0}", str);
        }
        #endregion
        static void Main(string[] args)
        {
            //DelegateChangeStart EventChargeStartPan1, EventChargeStartPan2, EventChargeStartPan3;//定义委托变量
    
            实现委托
            //EventChargeStartPan1 = TestWriteLine1;
            //EventChargeStartPan2 = TestWriteLine2;
            //EventChargeStartPan3 = TestWriteLine3;
    
            调用委托
            //EventChargeStartPan1("1");
            //EventChargeStartPan1("https://cdn.jxasp.com:9143/image/2");
            //EventChargeStartPan1("3");
    
            Console.WriteLine("****************结束****************");
    
    
            DelegateChangeStart EventChargeStartPan4;//定义委托变量
    
            EventChargeStartPan4 = TestWriteLine1;
            EventChargeStartPan4 += TestWriteLine2;
            EventChargeStartPan4 += TestWriteLine3;
            EventChargeStartPan4("四");
    
            Console.WriteLine("****************结束****************");
    
            Console.ReadLine();
        }
    }
    
      38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    在这里插入图片描述
    在这里插入图片描述

    3.移除一个委托实例中的方法 使用“-”

    public delegate void DelegateChangeStart(string str);//创建一个实例
    public class Program
    {
        #region 定义方法
        static void TestWriteLine1(string str)
        {
            Console.WriteLine("这里是方法一:{0}", str);
        }
        static void TestWriteLine2(string str)
        {
            Console.WriteLine("这里是方法二:{0}", str);
        }
        static void TestWriteLine3(string str)
        {
            Console.WriteLine("这里是方法三:{0}", str);
        }
        #endregion
        static void Main(string[] args)
        {
            //DelegateChangeStart EventChargeStartPan1, EventChargeStartPan2, EventChargeStartPan3;//定义委托变量
    
            实现委托
            //EventChargeStartPan1 = TestWriteLine1;
            //EventChargeStartPan2 = TestWriteLine2;
            //EventChargeStartPan3 = TestWriteLine3;
    
            调用委托
            //EventChargeStartPan1("1");
            //EventChargeStartPan1("https://cdn.jxasp.com:9143/image/2");
            //EventChargeStartPan1("3");
    
            //Console.WriteLine("****************结束****************");
    
    
            DelegateChangeStart EventChargeStartPan4;//定义委托变量
    
            EventChargeStartPan4 = TestWriteLine1;
            EventChargeStartPan4 += TestWriteLine2;
            EventChargeStartPan4 += TestWriteLine3;
            EventChargeStartPan4("四");
    
            Console.WriteLine("****************结束****************");
            EventChargeStartPan4 -= TestWriteLine2;
            EventChargeStartPan4("减后的四");
    
            Console.ReadLine();
        }
    }
    
      38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    在这里插入图片描述

    在这里插入图片描述

    其中EventChargeStartPan4 = TestWriteLine1;用“=”而不能“+=”,是因为之前EventChargeStartPan4 未实例化,可以使用下面的代码;
    但是如果使用以下方式,会出现编译错误: “DelegateChangeStart ”方法没有采用“0”个参数的重载;
    参考:http://www.tracefact.net/tech/009.html

    将方法作为参数传递

    委托可以让方法作为参数传递给其它方法:

    public delegate void DelegateChangeStart(string str);//创建一个实例
    public class Program
    {
        #region 定义方法
        static void TestWriteLine1(string str)
        {
            Console.WriteLine("这里是方法一:{0}", str);
        }
        static void TestWriteLine2(string str)
        {
            Console.WriteLine("这里是方法二:{0}", str);
        }
        static void TestWriteLine3(string str)
        {
            Console.WriteLine("这里是方法三:{0}", str);
        }
        #endregion
    
        static void Test(DelegateChangeStart str)
        {
            if (str != null)
            {
                str("5");
            }
        }
        static void Main(string[] args)
        {
            
            DelegateChangeStart EventChargeStartPan4= TestWriteLine1;//定义委托变量
    
            EventChargeStartPan4 = TestWriteLine1;
            EventChargeStartPan4 += TestWriteLine2;
            EventChargeStartPan4 += TestWriteLine3;
            EventChargeStartPan4("四");
    
            Console.WriteLine("****************结束****************");
            DelegateChangeStart EventChargeStartPan5 = TestWriteLine1;//定义委托变量实现
            Test(EventChargeStartPan5);
            EventChargeStartPan5("五");
    
            Console.ReadLine();
        }
    }
    
      38
    • 39
    • 40
    • 41
    • 42
    • 43

    在这里插入图片描述

    在这里插入图片描述

    事件
    事件自身就是委托类型,由于委托可以绑定和调用多个方法,所以会为事件的处理带来方便。类型只需要对外公开事件,就可以与外部的其它地方关联,从而实现事件订阅要在类中声明事件(只不过不管是不是声明为public,它总是被声明为private。另外,它还有两个方法,分别是add_MakeGreet和remove_MakeGreet,这两个方法分别用于注册委托类型的方法和取消注册。实际上也就是: “+= ”对应 add_MakeGreet,“-=”对应remove_MakeGreet。而这两个方法的访问限制取决于声明事件时的访问限制符。)

    1.首先要定义用来作为事件封装类型的委托,用event关键字来声明事件。
    2.为了允许派生类重写引发事件的代码,通常会在类中声明一个受保护的方法,习惯上命名On<事件名>

    public class Program
    {
        static void Main(string[] args)
        {
            
            PotInfo potinfo = new PotInfo();
            potinfo.EventChargeStartPan += Potinfo_EventChargeStartPan;//在输入+=后面按teb键就会自动生成一个事件处理的方法函数
            Console.WriteLine("按下任意键开始执行循环");
    
            Console.ReadLine();
            potinfo.Start();//开始执行
    
            Console.ReadLine();
        }
    
        private static void Potinfo_EventChargeStartPan()
        {
            Console.WriteLine("{0}  按下空格键", DateTime.Now.ToString());//按下事件显示当前时间文字输出
        }
    }
    
    
    public delegate void DelegateChangeStartHelper();//定义委托
    public class PotInfo
    {
        //声明事件
        public event DelegateChangeStartHelper EventChargeStartPan;
        protected virtual void OnEventChargeStartPan()
        {
            if (this.EventChargeStartPan != null)
            {
                EventChargeStartPan();
            }
        }
    
        public void Start()
        {
            while (true)
            {
                ConsoleKeyInfo keyinfo = Console.ReadKey();//读取键值
                if (keyinfo.Key == ConsoleKey.Spacebar)//按下空格键触发
                {
                    OnEventChargeStartPan();
                }
                if (keyinfo.Key == ConsoleKey.Escape)//按下esc键退出
                {
                    Console.WriteLine("{0}按下esc退出", DateTime.Now.ToString());
                    break;
                }
            }
        }
    }
    
      38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    在这里插入图片描述

    在这里插入图片描述

    DelegateHelper类参数
    如果针对不同的事件也定义一个对应的委托,数量一旦多起来,不好管理,为了解决这个问题,.NET类库提供了一个带有泛型参数的事件处理委托。

    public Action EventSweepCode;
    public void SweepCode(string value)
    {
    EventSweepCode(value);
    }

    Action<数据类型>此委托封装的方法的参数类型。此类型参数是逆变。即可以使用指定的类型或派生程度更低的类型。有关协变和逆变的更多信息,请参见泛型中的协变和逆变。

    public class DelegateHelper
    {
    public static DelegateHelper GetDelegateHelper;

        public static DelegateHelper Instance
        {
            get
            {
                if (null == GetDelegateHelper)
                {
                    GetDelegateHelper = new DelegateHelper();
    
                }
                return GetDelegateHelper;
            }
        }
    
    
        public Action<string> EventSweepCode;
        public void SweepCode(string value)
        {
        	if(EventSweepCode!=null){
            	EventSweepCode(value);
        	}
        }
    }
    
    public class Program
    {
        static void Main(string[] args)
        {
    
            DelegateHelper.Instance.EventSweepCode += Potinfo_EventChargeStartPan;//在输入+=后面按teb键就会自动生成一个事件处理的方法函数
            Console.WriteLine("输入任意值开始执行循环");
            Console.ReadLine();
            Console.WriteLine("开始执行");
            PotInfo potinfo = new PotInfo();
            potinfo.Start();//开始执行
    
            Console.ReadLine();
        }
    
        private static void Potinfo_EventChargeStartPan(string value)
        {
            Console.WriteLine("{0}  按下空格键", value.ToString());//按下事件显示当前时间文字输出
        }
    }
    
    public class PotInfo
    {
        public void Start()
        {
            while (true)
            {
                ConsoleKeyInfo keyinfo = Console.ReadKey();//读取键值
                if (keyinfo.Key == ConsoleKey.Spacebar)//按下空格键触发
                {
                    DelegateHelper.Instance.SweepCode(DateTime.Now.ToString());
                }
                if (keyinfo.Key == ConsoleKey.Escape)//按下esc键退出
                {
                    Console.WriteLine("{0}按下esc退出", DateTime.Now.ToString());
                    break;
                }
            }
        }
    }
    
      38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63

    在这里插入图片描述

    在这里插入图片描述

    相关技术文章

    点击QQ咨询
    开通会员
    返回顶部
    ×
    微信扫码支付
    微信扫码支付
    确定支付下载
    请使用微信描二维码支付
    ×

    提示信息

    ×

    选择支付方式

    • 微信支付
    • 支付宝付款
    确定支付下载