筆記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;
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章