C#:委托

委托本质是C语言中的函数指针

using System;

namespace _01_委托
{/// <summary>
/// 委托是一个数据类型,可以定义变量
/// 委托定义变量和类非常相似,它是用来存储方法的
/// </summary>
    class Program
    {
        static void Main(string[] args)
        {
            //2、使用委托第二步:声明委托变量,并赋值。
            //声明了一个委托变量md,并且new了一个委托对象,并且把方法M1传递进去
            //即md委托保存了M1方法。
            MyDelegate md = new MyDelegate(M1);
            //3、调用了md委托的时候就相当于调用了M1方法。
            md();
            Console.WriteLine("ok");
            Console.ReadKey();
        }
        static void M1()
        {
            Console.WriteLine("我是没有返回值,没有参数的方法");
        }
    }
    //1、使用委托第一步:定义委托类型
    //定义了一个委托类型,用来保存无参数,无返回值的方法
    //定义了一个名字叫MyDelegate的类型,是个委托,只能存储无返回值,无参数的方法
    public delegate void MyDelegate();
}

以上是委托的使用过程:

1、先定义

2、赋值

3、使用

案例:先创建一个类TestClass,该类中有DoSomething方法(假设有5条语句),调用该类的对象时,DoSomething方法当然操作都相同。但是,现在第三条语句打印系统时间,可能是打印到中控台,也可能是写到文件里,也可能是写到数据库里等等很多种可能,我们不能列举所有的可能,通过委托来实现。

using System;

namespace 委托使用案例
{
    public class TestClass
    {
        public void DoSomething(WrieTimeDelegate writeTime)
        {
            Console.WriteLine("=========================");
            Console.WriteLine("=========================");
            //将下一行代码写活,不要写死
            //Console.WriteLine(System.DateTime.Now.ToString());
            //writeTime();
            if(writeTime!=null)
            {
                writeTime();
            }
            Console.WriteLine("=========================");
            Console.WriteLine("=========================");
        }

        //public void ChangeStrings(string [] strs)
        //{
        //    for (int i = 0; i < strs.Length; i++)
        //    {
        //        strs[i] = "★" + strs[i] + "★";
        //    }
        //}

        public void ChangeStrings(string[] strs,GetStringGelegate change)
        {
            for (int i = 0; i < strs.Length; i++)
            {
                strs[i] = change(strs[i]);
            }
        }

        public delegate string GetStringGelegate(string name);
        //定义一个委托,一个用来存储没有返回值,没有参数的委托
        public delegate void WrieTimeDelegate();
    }
}
//举例:button按钮是一个类,点击button可以连数据库,也可以连接文件,也可以弹出对话框等,做什么都可以,不需要定义不同的方法,按钮类内部就是通过内部一系列不同的委托来实现的不同功能

打印到中控台

using System;
using 委托使用案例;

namespace _01_控制台打印
{
    class Program
    {
        static void Main(string[] args)
        {
            TestClass tc = new TestClass();
            //DoSomething的参数是一个方法名PrintToConsole,用C语言的理解话,就是类中的函数指针指向了PrintToConsole方法
            tc.DoSomething(PrintToConsole);
            Console.ReadKey();
        }
        //
        static void PrintToConsole()
        {
            Console.WriteLine(System.DateTime.Now.ToString());
        }
    }
}

打印到文件:

using System;
using System.IO;
using 委托使用案例;

namespace _02_写到文本文件里
{
    class Program
    {
        static void Main(string[] args)
        {
            TestClass tc = new TestClass();
            //写到文件里,WriteToFiel作为参数
            tc.DoSomething(WriteToFiel);
            Console.ReadKey();
        }
        static void WriteToFiel()
        {
            File.WriteAllText("time.txt", System.DateTime.Now.ToString());
        }
    }
}

案例:还是在类TestClass中,通过不同的方法ChangeStrings或者ChangeStrings1做参数,实现大写或者小写。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using 委托使用案例;

namespace _03_委托_字符串举例
{
    class Program
    {
        static void Main(string[] args)
        {
            TestClass tc = new TestClass();
            string[] names = new string[] { "ZhangSan", "LiSi", "WangWu" };
            tc.ChangeStrings(names,ChangeStrings);
            for (int i = 0; i < names.Length; i++)
            {
                Console.WriteLine(names[i]);               
            }
            Console.ReadKey();
        }
        static string ChangeStrings(string name)
        {
            return name.ToUpper();
        }
        static string ChangeStrings1(string name)
        {
            return name.ToLower();
        }
    }
}

匿名:

using System;

namespace _02_匿名方法
{
    public delegate void MyDelegate();
    public delegate void MyDelegate1(string msg);
    public delegate int MyDelegate2(int x, int y);
    class Program
    {
        static void Main(string[] args)
        {
            //匿名方法
            //匿名方法不在类中定义,而是在给委托变量赋值的时候,需要赋值一个方法,用现做现卖的方式,定义一个匿名方法传递给委托
            Console.WriteLine("这是正常的委托方法使用");
            MyDelegate md = M1;
            md();
            Console.WriteLine("=====================");

            Console.WriteLine("无参数无返回值的匿名方法");
            MyDelegate mdd = delegate ()
            {
                Console.WriteLine("匿名方法打印的:OK!");
            };
            mdd();

            //有参数无返回值的匿名方法
            Console.WriteLine("=====================");
            MyDelegate1 md1 = delegate (string msg)
            {
                Console.WriteLine("有参数无返回值的匿名方法打印的:" + msg);
            };
            md1("OK");

            //有参数有返回值的匿名方法
            Console.WriteLine("=====================");
            MyDelegate2 md2 = delegate (int x, int y)
            {
                return x * x + y * y;
            };
            Console.WriteLine("有参数无返回值的匿名方法打印的{0}:", md2(3, 4));

            //无参数无返回值的匿名方法用lambda表达式写法
            Console.WriteLine("=====================");
            MyDelegate m = () => { Console.WriteLine("lambda表达式"); };
            m();

            //有1个参数无返回值的匿名方法用lambda表达式写法,lambda表达式从来不需要传数据类型的
            Console.WriteLine("=====================");
            MyDelegate1 m1 = mm => { Console.WriteLine(mm); };
            m1("are you ok?");


            //有多个参数无返回值的匿名方法用lambda表达式写法,lambda表达式从来不需要传数据类型的
            Console.WriteLine("=====================");
            MyDelegate2 m2 = (x, y) => { return (x + y); };
            int temp = m2(3, 4);
            Console.WriteLine(temp);


            //
            

            Console.ReadKey();
        }
        static void M1()
        {
            Console.WriteLine("OK!");
        }
    }
}

泛型委托:

using System;

namespace _03_泛型委托
{
    public delegate void MyGenericDelegate<T>(T args);
    class Program
    {
        static void Main(string[] args)
        {
            //Action:无返回值的委托,系统给的
            //Action<>:无返回值的委托,泛型版本的,最多16个参数
            //Func<>:有返回值的委托,没有非泛型版本的
            //MyGenericDelegate<string> md = M1;
            //md("aaa");

            Action<string> a1 = m => { Console.WriteLine(m); };
            a1("雷猴");
            Action<int, int> a2 = (x, y) => { Console.WriteLine(x + y); };
            a2(3, 5);

            //Func<>:有返回值的委托,没有非泛型版本的,最多8个参数,返回值都只有1个
            Func<int> f = () => { return 100; };
            int result = f();
            Console.WriteLine(result);

            //Func<int, int, int>最后一个参数是返回值类型,这里参数是2个,返回值1个,一共3个
            Func<int, int, int> f1 = (x, y) => { return x + y; };
            int result1 = f1(3, 50);
            Console.WriteLine(result1);


            Console.ReadKey();
        }

        static void M1(string msg)
        {
            Console.WriteLine(msg);
        }
    }
}

事件,也是委托,有点特殊的委托

using System;
using System.Threading;

namespace _04_事件
{
    #region 用委托处理播放器
    //class Program
    //{
    //    static void Main(string[] args)
    //    {
    //        MusicPlayer mp3 = new MusicPlayer();
    //        mp3.AfterStartedPlay = () =>
    //        {
    //            Console.WriteLine("加载歌词");
    //        };
    //        mp3.BeforeStopPlay = () =>
    //        {
    //            Console.WriteLine("删除歌词");
    //        };

    //        mp3.StartPlay();
    //        mp3.StopPlay();
    //        //如果把上两行注释掉,执行下面两行,也能执行,但是逻辑不对,因为没有播放就加载歌词了,因为委托必须是public,所以外界随意访问
    //        //mp3.BeforeStopPlay(); 
    //        //mp3.AfterStartedPlay();
    //        //也可以对委托赋值,如下面两行,这样就失去意义
    //        //mp3.AfterStartedPlay = null;
    //        //mp3.BeforeStopPlay = null;
    //        //以上两点,既可以随意访问,又可以随意赋值,不符合逻辑


    //        Console.ReadKey();
    //    }
    //}
    //public class MusicPlayer
    //{
    //    //做几个事件
    //    //音乐播放后显示歌词
    //    public Action AfterStartedPlay;
    //    //音乐停止前关闭歌词
    //    public Action BeforeStopPlay;

    //    private void PlayMusic()
    //    {
    //        Console.WriteLine("开始播放音乐!");
    //    }
    //    public void StartPlay()
    //    {
    //        PlayMusic();
    //        //音乐播放之后触发该事件
    //        if(AfterStartedPlay!=null)
    //        {
    //            AfterStartedPlay();
    //        }
    //        Thread.Sleep(2000);
    //    }
    //    public void StopPlay()
    //    {
    //        //音乐结束之前触发该事件
    //        if (BeforeStopPlay != null)
    //        {
    //            BeforeStopPlay();
    //        }
    //        Console.WriteLine("播放结束!");
    //    }
    //}
    #endregion

    #region 用事件event处理播放器
    class Program
    {
        static void Main(string[] args)
        {
            MusicPlayer mp3 = new MusicPlayer();
            mp3.AfterStartedPlay += new Action(Mp3_AfterStartedPlay);
            mp3.BeforeStopPlay += new Action(Mp3_BeforeStopPlay);
            mp3.StartPlay();
            mp3.StopPlay();

            //事件不能再外部调用,所以下列调用无效
            //事件只能在定义时间的类的内部来触发
            //mp3.AfterStartedPlay();

            Console.ReadKey();
        }

        private static void Mp3_AfterStartedPlay()
        {
            Console.WriteLine("加载歌词");
        }

        private static void Mp3_BeforeStopPlay()
        {
            Console.WriteLine("删除歌词");
        }
    }
    public class MusicPlayer
    {
        //做几个事件
        //音乐播放后显示歌词,加了event
        public event Action AfterStartedPlay;
        //音乐停止前关闭歌词
        public event Action BeforeStopPlay;

        private void PlayMusic()
        {
            Console.WriteLine("开始播放音乐!");
        }
        public void StartPlay()
        {
            PlayMusic();
            //音乐播放之后触发该事件
            if (AfterStartedPlay != null)
            {
                AfterStartedPlay();
            }
            Thread.Sleep(2000);
        }
        public void StopPlay()
        {
            //音乐结束之前触发该事件
            if (BeforeStopPlay != null)
            {
                BeforeStopPlay();
            }
            Console.WriteLine("播放结束!");
        }
    }

    #endregion
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值