筆記10 事件、項目實戰、結構體
- 回顧委託的寫法
- 新建一個類Test.cs(順序1)
- 在Program.cs裏實例化一個Test (順序2)
- 寫一個委託(delegate。順序5)
- 聲明一個委託(順序6)
- 寫一個構造方法(順序4),調用有兩種方法(順序7)
- 寫一個需要委託的方法(順序3)
- 事件(比委託多了一個evevt,圖標是閃電)
- 項目實戰
- 位置:AudioPlayer.cs(內部)
- 磁帶(順序1)
- 定時器(順序3)
- 索引【初寫最外層,補充1】
- 播放回調{把歌詞回調到最外層。順序a:聲明委託}
- 結束播放回調
- 構造方法(順序4。實例化定時器,到時觸發事件)
- 播放中,定時器觸發的方法(綁定定時器)【初寫最外層,補充:3:播放磁帶裏的內容】{把歌詞回調到最外層。順序b}
- 寫個方法,裝載磁帶(順序2)
- 播放【初寫最外層,補充2:請空索引】
- 停止
- 位置:Program.cs(最外層)
- 錄音機
- 如果是多盤磁帶,則需補充磁帶及其索引
- 調用方法{把歌詞回調到最外層。順序d}
- 多盤磁帶循環,需將上面的創建磁帶、加載磁帶做如下修改
- 播放中的方法。{把歌詞回調到最外層。順序c}
- 開始播放的方法。
- 結束播放的方法(如果是多盤磁帶,需在下面補充)
- 示意圖
- 結構體
回顧委託的寫法
新建一個類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;
}