笔记10 事件、项目实战、结构体

笔记10 事件、项目实战、结构体

回顾委托的写法

新建一个类Test.cs(顺序1)

在Program.cs里实例化一个Test (顺序2)

       static void Main(string[] args)
        {
            //实例化一个Test
            Test test = new Test();

            Console.ReadKey();
        }   

写一个委托(delegate。顺序5)

参数重要的是类型必须与要保存的方法一致,叫什么名无所谓。

    //先写个委托。名字是Add。两个参数重要的是必须是int类型,叫什么名无所谓。
        public delegate void Add(int aaa, int bbb);   

声明一个委托(顺序6)

        //声明一个委托。Add是上面写的委托名字。add是委托类型的变量。
        public Add add;

add这个变量与其他变量的区别:例如public int a;中,a是int类型的。
类比得,add是Add类型(方法类型)。
add相当于普通变量,只不过它里面就是保存个方法。

写一个构造方法(顺序4),调用有两种方法(顺序7)

法一:new一个Add,将方法当参数传给它

         //构造方法
        public Test()
        {
            //func(3, 4);  正常调用方法的方式:方法名称();

            //法一:new一个Add,将方法当参数传给它 。
            add = new Add(func);
            add(3,4);
        }  
//结果:7

法二:利用+=和-=

        public Test()
        {
           //法二:
            add += func;
            add(3,4); 
        }
//结果:7   

写一个需要委托的方法(顺序3)

委托相当于函数指针,在c#里相当于一个变量,用来保存方法。
保存了方法,这个变量就能像方法一样使用了。

        //这个方法就是传两个参,然后把两个参的和打印出来。
         public void func(int a, int b)
        {
            Console.WriteLine(a + b);
        }   

事件(比委托多了一个evevt,图标是闪电)

事件是对委托的封装。
事件主要是相对于控件来说的。比如桌面开发,控件时用事件,回调时用委托。
对游戏开发来说,二者一样,而且用委托用的多,用事件用的少。
事件是在写了委托的基础上,进行的。比如在声明一个委托(顺序6)后,声明一个事件(顺序7)

声明一个委托(顺序6)

        //声明一个委托。Add是上面写的委托名字。add是委托类型的变量。
        public Add add;

声明一个事件(evevt。顺序7)

        //声明一个事件,对委托的封装
        public event Add addEvent;   

调用方法(两种。顺序8)

法一:new一个Add,将方法当参数传给它

        public Test()
        {
            //事件
            addEvent = new Add(func);
            addEvent(5, 6);
        } 
/*结果:7(委托的结果)
       11(事件的结果)  */   

法二:利用+=和-=

        public Test()
        {
            //事件
            addEvent += func;
            addEvent(5, 6);
        } 
/*结果:7(委托的结果)
       11(事件的结果)  */

项目实战

类:1、录音机 2、磁带(存一首歌/个)

位置:AudioPlayer.cs(内部)

磁带(顺序1)

       //磁带。private封装
        private AudioClip clip;   

定时器(顺序3)

        //定时器
        System.Timers.Timer timer;   

索引【初写最外层,补充1】

        //索引
        private int index;  

播放回调{把歌词回调到最外层。顺序a:声明委托}

 /*播放回调(委托)。
 AudioPlaying播放中的一个回调,void没有返回值,参数是char类型(字),每次传一个字过去。*/
        public delegate void AudioPlaying(char c);
        //声明一个委托。有了audioPlaying这个变量(委托类型的)。
        public AudioPlaying audioPlaying;   

 /*声明一个委托audioPlaying,用来保存上面void AudioPlaying(char c)这个结构的一个方法。
  这个方法返回值,参数是char类型(字)。*/

结束播放回调

 //结束播放回调
        public delegate void AudioEnd(string name);
        public AudioEnd audioEnd;  

构造方法(顺序4。实例化定时器,到时触发事件)

        //构造方法
        public AudioPlayer()
        {
            //实例化定时器(毫秒。1秒=1000毫秒)500即每隔半秒出一个字
            timer = new System.Timers.Timer(500);
       
            //到时触发事件
            timer.Elapsed += playing;
 /*写完等于号,按两下Tab键,会自动出现右边Timer_Elapsed以及下面的方法。
 我们给它改个名叫playing*/
        }   

播放中,定时器触发的方法(绑定定时器)【初写最外层,补充:3:播放磁带里的内容】{把歌词回调到最外层。顺序b}

上面的到时触发事件,写完等于号,按两下Tab键,会自动出现此方法。
我们给它改个名叫playing。

        //播放中,定时器触发的方法(绑定定时器)。只要开始播放,没隔半秒调用这个方法
        private void playing(object sender, System.Timers.ElapsedEventArgs e)
        {
           /*播放磁带里的内容(补充)。因为要一个字一个字的播放,所以需要索引。
           播到哪里?注意不能越界*/
            if(index < clip.Content.Length)
            {
                //Console.Write(clip.Content[index++]);    //把歌词写出来
                /*此时已经可以在程序里看到歌词一个字一个字出现,
                但应该把歌词回调到最外层,便要用到委托了。*/

                //把歌词回调到最外层{顺序b}
                if (audioPlaying != null)
                {
                    //如果这个audioPlaying不为空,即委托存在,调用委托
                    audioPlaying(clip.Content[index++]);
                    //这个audioPlaying委托保存的方法在哪里?写在最外层。
                } 
            } else
            {
                //播放结束
                Stop();
            }
        }   

写个方法,装载磁带(顺序2)

        //写个方法,装载磁带。外界可以传进来AudioClip clip(即顺序1的)
        public void LoadClip(AudioClip clip)
        {
       /*由于这里的clip和顺序1的clip重名,所以下面用this区分。
         有this的是当前类的变量,无this的是参数*/
            this.clip = clip;
        }   

播放【初写最外层,补充2:请空索引】

        //播放
        public void Play()
        {
            //如果有磁带,播放。clip加载磁带
            if (clip != null)
            {
                //请空索引(补充)。确保每次播放从0开始
                index = 0; 
                
                timer.Start();
               
               //如果存在播放回调,就调用回调
                if(audioStar != null)
                {
                    audioStar(clip.Name);    //把歌名传出去
                }
            }
        }   

停止

        //停止
        public void Stop()
        {
            //如果有磁带,播放。clip加载磁带
            if(clip != null)
            {
                timer.Stop();
                 //如果存在结束回调,就调用回调
                if(audioEnd != null)
                {
                    audioEnd(clip.Name);
                }
            }
        }   

位置:Program.cs(最外层)

录音机

        //录音机
        public static AudioPlayer player;   

如果是多盘磁带,则需补充磁带及其索引

        //磁带
        public static AudioClip[] clips;
        //当前磁带索引
        public static int index = 0;

调用方法{把歌词回调到最外层。顺序d}

static void Main(string[] args)
        {
            //创建录音机
            player = new AudioPlayer();

           //播放委托。把歌词回调到最外层{顺序d}
            player.audioPlaying = new AudioPlayer.AudioPlaying(playing);
            //开始播放委托
            player.audioStar = new AudioPlayer.AudioStar(StartPlay);
            //结束委托
            player.audioEnd = new AudioPlayer.AudioEnd(EndPlay);

            //创建磁带
            AudioClip clip = new AudioClip("冰雨", "冷冷的冰雨在脸上胡乱地拍");
            //加载磁带
            player.LoadClip(clip);
            //播放
            player.Play();

            Console.ReadKey();
        }   

多盘磁带循环,需将上面的创建磁带、加载磁带做如下修改

            //创建磁带
            clips = new AudioClip[3];
            clips[0] = new AudioClip("冰雨", "冷冷的");
            clips[1] = new AudioClip("小苹果", "你是我的");
            clips[2] = new AudioClip("凉凉", "凉凉夜色");

            //加载磁带
            player.LoadClip(clips[index++]);

播放中的方法。{把歌词回调到最外层。顺序c}

        //播放中的方法。委托要保存的方法
        public static void playing(char word)
        {
            Console.Write(word);
        }  

开始播放的方法。

   //开始播放的方法。传过来歌曲名称
        public static void StartPlay(string name)
        {
            Console.WriteLine("开始播放:" + name);
        }  

结束播放的方法(如果是多盘磁带,需在下面补充)

   //结束播放
        public static void EndPlay(string name)
        {
            Console.WriteLine("");     //打印空的字符串。此处是换行的作用
            Console.WriteLine("结束播放:" + name);
            
             //如果还有下一盘磁带,换磁带播放(补充)
            if (index < clips.Length)
            {
                player.LoadClip(clips[index++]);
                player.Play();
            }
        }  

示意图

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

结构体

类(属于引用类型)

在这里插入图片描述

结构体struct(属于值类型)

特点:不能继承,没有多态。
作用:用来储存简单数据的。
与类的区别:结构体不需要new。
在这里插入图片描述

class Test
    {
     void func2()
        {
            //结构体不需要new,声明出来就可以用
            Enemy enemy;
            enemy.Name = "东方不败";

            Enemy enemy2 = enemy;
            enemy.Name = "林平之";
            Console.WriteLine(enemy.Name);
        }
    }  
    //结构体(值类型)
    struct Enemy
    {
        public string Name;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值