LOSo講解
C#
在我的LOSoMan的委派講解筆記裡,已經清楚地介紹了委派的用法及用途。
通常我們講到事件會先提到委派的原因是因為事件的參數型別是從委派宣告出來的,舉個例子:
public delegate void MyHandler(object sender, MyEventArgs arg);
public event MyHandler MySomeWorks;
這裡可以明確的了解"MyHandler"是自創的委派型別,而"MySomeWorks"正是這個型別的事件。
其中"MyEventArgs"為一個繼承"EventArgs"的自訂類別,程式部分為:
public class MyEventArgs : EventArgs
{
public EAnimalType Animal = EAnimalType.none;
public EMotionType Motion = EMotionType.none;
}
這兩個方法(Method)在委派事件扮演重要的角色:
在本次演示的程式中,訂閱者(subscriber)方法負責變更UI介面的顯示:
private void MySubscriber(object sender, MyEventArgs arg)
{
if (arg.Animal != EAnimalType.none && arg.Motion != EMotionType.none)
{
rtbShow.AppendText(string.Format("{0}正在{1}\n", arg.Animal, arg.Motion));
}
else if (arg.Animal != EAnimalType.none && arg.Motion == EMotionType.none)
{
rtbShow.AppendText(string.Format("{0}很寂寞\n", arg.Animal));
}
else
{
rtbShow.AppendText("格式錯誤\n");
}
}
而發佈者(publisher)則是單純提供使用,並且在發佈者方法內去呼叫(Invoke)執行事件所註冊的方法,所以在這的程式碼為:
private void MyPublisher(object sender, MyEventArgs arg)
{
if (MySomeWorks != null)
{
MySomeWorks.Invoke(sender,arg);
}
}
由此可見,publisher所做的就只是先判斷事件是否被註冊,若有被註冊則去執行事件所註冊的方法。
當我們的事件(Event)如委派(Delegate)一樣就是個容器,若事件未被註冊,則其為空的(null)。所以我們一樣可以利用+=及-=的方式將訂閱者方法加入或是移出事件這個容器。
因此在我們要演示的程式碼中只需要註冊一次:
MySomeWorks += MySubscriber;
左側的"MySomeWorks"即為剛才宣告的事件,而右側則為訂閱者方法。意思就如同我們將一顆蘋果放入籃子裡。
而當我們要執行時,只需使用剛才的發佈者方法即可:
MyPublisher(sender,arg);
sener為object型別的參數;arg為MyEventArgs型別的參數
首先配置一個UI介面,如下:
Learn More →
然後主程式如下:
public partial class Form1 : Form
{
public delegate void MyHandler(object sender, MyEventArgs arg);
public event MyHandler MySomeWorks;
public Form1()
{
InitializeComponent();
MySomeWorks += MySubscriber;
Initcbx();
}
private void Initcbx()
{
foreach (EAnimalType x in Enum.GetValues(typeof(EAnimalType)))
{
cbxAnimal.Items.Add(x.ToString());
}
foreach (EMotionType y in Enum.GetValues(typeof(EMotionType)))
{
cbxMotion.Items.Add(y.ToString());
}
cbxAnimal.Text = EAnimalType.none.ToString();
cbxMotion.Text = EMotionType.none.ToString();
}
private void btnShow_Click(object sender, EventArgs e)
{
MyEventArgs arg = new MyEventArgs();
arg.Animal = (EAnimalType)Enum.Parse(typeof(EAnimalType),cbxAnimal.Text);
arg.Motion = (EMotionType)Enum.Parse(typeof(EMotionType), cbxMotion.Text);
MyPublisher(sender,arg);
}
private void MySubscriber(object sender, MyEventArgs arg)
{
if (arg.Animal != EAnimalType.none && arg.Motion != EMotionType.none)
{
rtbShow.AppendText(string.Format("{0}正在{1}\n", arg.Animal, arg.Motion));
}
else if (arg.Animal != EAnimalType.none && arg.Motion == EMotionType.none)
{
rtbShow.AppendText(string.Format("{0}很寂寞\n", arg.Animal));
}
else
{
rtbShow.AppendText("格式錯誤\n");
}
}
private void MyPublisher(object sender, MyEventArgs arg)
{
if (MySomeWorks != null)
{
MySomeWorks.Invoke(sender,arg);
}
}
}
public enum EAnimalType
{
none,
狗,
貓,
鳥,
}
public enum EMotionType
{
none,
吃,
叫,
動,
}
public class MyEventArgs : EventArgs
{
public EAnimalType Animal = EAnimalType.none;
public EMotionType Motion = EMotionType.none;
}
執行後,在Animal combobox 點選"狗";在Motion combobox 點選"吃",按下"show"按鈕,演示結果為:
因為個人在剛接觸c#時,對於委派事件有些疑惑,對於使用時機十分不解。但是,經過兩三個月的薰陶,對於委派事件有進一步的認識與理解。
對於事件的使用時機,分析如下:
委派事件是時常用到的跨層傳遞方式,在MVC架構裡的使用,則以Model資料改變後,想連動回UI(View)的顯示時,時常使用。個人最近在寫得依些小程式,也曾使用靜態事件去連動多個UI層級的刷新。總之,是個不可或缺的好用工具。
物件導向編程(Object-oriented programming),縮寫OOP。顧名思義這種編程方式就是將程式封裝成一種物件,在使用上就會提高軟體的重用性、靈活性和擴充性。而通常一個物件(object)指的就是一個類別(class)的實例,類別可以提供公開的欄位(field)、屬性(attribute)、方法(method),使其他的程式碼可以呼叫使用,而我們的專案程式就是由物件們產生關聯而成的。
Mar 6, 2023什麼是XML? XML為可延伸標記式語言,可用來傳送與攜帶資料資訊。那麼,XML跟HTML有什麼差別呢? XML著重在內容 HTML強調布局 而且,他們的格式寫法及用法也稍微不同: XML的元素名稱有分大小寫。HTML的標籤不分大小寫。 XML的元素一定都要有起始標籤和結尾標籤。而HTML的元素在某些情況下,可以不寫結尾標籤。
May 11, 2022Socket通訊概論 Socket通訊為使用Ethernet傳輸資訊的一種方式。運作的方式就如同電話撥接,透過設定插座的號碼,其他人就可透過這串號碼與其通話。而Socket的號碼就是IP Number加上TCP Port。 Socket的連線端可以分為主機端(Server)及客戶端(Client)。通常Server要先設定並連接上傳輸埠口,才能開始監聽是否有Client請求連接;而Client也一樣要連接上傳輸埠口,才能發送要求連線。而當通訊結束時,則會互相確認要中斷連線。 C#裡的Socket類別及常用方法 在C#程式裡,提供了Socket類別讓programmer可以更簡單的設計出可連線的應用程式。 Socket類別的宣告,如:(參閱連結)
May 11, 2022委派的定義 Microsoft手冊上所說,委派(Delegate)為一種類型,只要有相同簽章和傳回型別的方法,都可與定義好的委派產生關聯。之後要使用時,先定義一個委派呼叫方法,然後帶入參數即可。 Microsoft手冊也說委派是可以安全封裝方法的類型。這句話對我而言,就好比委派一個可以裝載方法的容器,你可以把方法放入委派這個容器之中,自然也可以將方法從容器中卸載。而當我們要使用這個容器裡所有存放的方法,就只需要呼叫(Invoke)這個容器就行了。 宣告委派 話不多說,先來看看如何宣告一個委派: public delegate void NonDelegate(); public delegate void MyDelegate(int A);
May 11, 2022or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up