代碼
1. 委託的定義:
委託是函數的封裝,它代表一"類"函數.
他們都符合一定的簽名:擁有相同的參數列表,傳回值類型.同時,委託也可以看成是對函數的抽象,是函數的"類".此時,委託的執行個體將代表一個具體的函數.
委託聲明和定義了一個參考型別,它用來封裝方法,用指定的簽名來封裝方法.一個委託的執行個體,可以封裝靜態或者執行個體方法.
委託是一種引用的類型,一旦為委託分配了方法,委託將與該方法完全相同的行為,委託方法的使用可以像其他任何方法一樣, 具有參數和傳回值
委託的一個特徵是它們的類型是安全的.可以確保被調用的方法簽名是正確的,但他們並不關心調用該方法的是什麼類型的對象,甚至不考慮該方法是靜態方法還是執行個體方法.(給定委託的執行個體可以表示任何類型的任何對象上的執行個體方法或靜態方法,只要方法的簽名匹配於委託的簽名就可以).
2. 委託的使用:
當要把方法傳遞給其他方法時,需要使用委託.
為什麼什麼用委託:
更加靈活的方法調用.
用於非同步回調.
多線程編程中使用委託來定啟動一個線程時調用的方法.
C#中的事件模型,用他們來指明處理給定事件的方法.
例:
class Program
{
//定義委託
delegate double ProcessDelegate(double param1, double param2);
static double Multiply(double param1, double param2)
{
return param1 * param2;
}
static double Divide(double param1, double param2)
{
return param1 / param2;
}
static void Main(string[] args)
{
//定義委託變數
ProcessDelegate pd;
double param1 = 20;
double param2 = 10;
Console.WriteLine("Enter M to multiply or D to divide");
string input = Console.ReadLine();
if (input == "M")
{
//初始化委託變數,要把一個函數引用賦給委託變數,
//參數是要使用的函數名,且不帶括弧.
pd = new ProcessDelegate(Multiply);
}
else
{
pd = new ProcessDelegate(Divide);
}
//使用該委託調用所選函數
Console.WriteLine("Result: {0}",pd(param1,param2));
Console.ReadKey();
}
3. 多播委託: 引用多個方法的委託,它連續調用每個方法.
為了把委託的單個執行個體合并為一個多播委託,委託必須是同類型的,傳回型別必須是void,不能帶輸出參數out(可以帶引用參數ref).
多播委託應用於事件模型中.
//聲明委託
public delegate void myDelegate();
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public void aa()
{
Console.WriteLine("aa");
}
public void bb()
{
Console.WriteLine("bb");
}
public void cc()
{
Console.WriteLine("cc");
}
myDelegate md;
private void button1_Click(object sender, EventArgs e)
{
md = new myDelegate(aa);
md += new myDelegate(bb);
myDelegate m = new myDelegate(cc);
md += m ;
md();
}
}
4. 非同步回調:
由於執行個體化委託是一個對象,所以可以將其作為參數進行傳遞.也可以將其賦值給屬性.這樣,方法便可以將一個委託作為參數來接受,並且以後可以調用該委託.這樣稱為非同步回調,是在較長的進程完成後用來通知調用方的常用方法.以這種方式使用委託時,使用委託的代碼無需瞭解有關所用方法的實現方面的任何資訊.
回調的另一個常見用法是定義自訂的比較方法並將該委託傳遞給排序方法.
例:
//定義委託
delegate void Del(int a,int b);
class Program
{
static void Main(string[] args)
{
Program p = new Program();
Del d = new Del(p.F_min); //執行個體化委託並傳給他比較的方法.
p.CallBack(10, 30, d); //調用回呼函數
}
//回呼函數,將委託執行個體作為方法參數進行傳遞.
public void CallBack(int a,int b,Del d)
{
d(a, b); //執行委託
}
//輸出較大的數
public void F_max(int a, int b)
{
Console.WriteLine("大的那個數為: " + Math.Max(a,b));
}
//輸出較小的數
}
5. 匿名方法
匿名方法允許我們以一種”內聯”的方式來編寫方法代碼,將代碼直接與委託執行個體相關聯,從而使得委託執行個體化的工作更加直觀和方便.
使用例子:
class Program{
//定義委託
public delegate string dTest(string val);
static void Main(string[] args){
string mid = "男子足球隊";
//匿名方法
dTest aDelegate = delegate(string param){
param += mid;
param += "加油.";
return param;
};
Console.WriteLine(aDelegate("中國"));
Console.ReadLine();
}
}
如果委託類型的傳回型別為void,匿名方法裡便不能返回任何值.如果不為void,匿名方法裡返回的值必須和委託類型的傳回值相容.
6. 何時使用委託,何時介面?
委託:
當使用事件設計模式時.
當封裝靜態方法可取時.
當調用方不需要訪問實現該方法的對象中的其他屬性方法或介面時.
需要方便的組合.
當類可能需要該方法的多個實現時.
介面:
當存在一組可能被調用的相關方法時.
當類只需要方法的單個實現時.
當使用介面的類想要將該介面強制轉換為其他介面或類類型時.
public void F_min(int a, int b)
{
Console.WriteLine("小的那個數為: " +Math.Min(a,b));
}